所用技術(shù)棧
- JavaScript
- python
- tornado
- madtornado
該文所用到的一切資源
注意事項(xiàng)
- 本文封裝的upload.js沒有完全耦合后端的madtornado進(jìn)行實(shí)現(xiàn)猖毫,但是結(jié)合madtornado接口方案可以更加便利完成分片上傳任務(wù)
- 本文后端使用的python+tornado的結(jié)合,但是tornado并非原生tornado而是被封裝后的madtornado释簿,madtornado讓tornado使用起來更加簡(jiǎn)單蕉斜,但是使用者需要有tornado使用經(jīng)驗(yàn),并結(jié)合madtornado文檔才能充分使用
前端實(shí)現(xiàn)
upload.js接口說明
ffeach() 創(chuàng)建FileForeach對(duì)象工廠函數(shù)
參數(shù): file(必填) File對(duì)象
參數(shù): chunkSize(選填) 單個(gè)文件塊大小怕膛,單位bytesnew FileForeach() 文件分塊函數(shù)熟嫩,主要用于文件提取分割后的數(shù)據(jù)塊
參數(shù): file(必填) File對(duì)象
參數(shù): chunkSize(選填) 單個(gè)文件塊大小,單位bytesFileForeach#isOutRange() 判斷文件是否超出可提取的大小
FileForeach#nextLoad() 獲取下一個(gè)文件塊褐捻,返回Blob對(duì)象
FileForeach#forEach() 遍歷File對(duì)象切割的文件塊
參數(shù): callback(必填) 回調(diào)函數(shù)掸茅,接收一個(gè)blob對(duì)象為文件數(shù)據(jù)塊
注意:當(dāng)數(shù)據(jù)塊被遍歷完畢后,將無法再產(chǎn)出文件塊柠逞,F(xiàn)ileForeach不保存任何數(shù)據(jù)塊昧狮,為了節(jié)省空間
如果需要二次遍歷,需要重新創(chuàng)建FileForeach對(duì)象
hashFile() 對(duì)文件進(jìn)行hash運(yùn)算板壮,該方法異步執(zhí)行
參數(shù): file(必填) File對(duì)象
參數(shù): callback(選填) 接收運(yùn)算完的hash結(jié)果值函數(shù)
參數(shù): chunkSize(選填) 單個(gè)文件塊大小逗鸣,單位byteshashFilePromise() 對(duì)文件進(jìn)行hash運(yùn)算,該方法異步執(zhí)行绰精,并且會(huì)返回Promise對(duì)象
參數(shù): file(必填) File對(duì)象
參數(shù): chunkSize(選填) 單個(gè)文件塊大小撒璧,單位bytesfetchFile() 上傳文件塊
參數(shù): address(必填) URL請(qǐng)求地址
參數(shù): md5(必填) 文件md5值
參數(shù): block(必填) 當(dāng)前文件塊的索引
參數(shù): data(必填) 文件塊數(shù)據(jù)
upload.js前端使用案例
let fileEl = document.getElementById("file");
let uploadAddress = "http://127.0.0.1:8095/file/upload";
let mergeAddress = "http://127.0.0.1:8095/file/merge";
// 點(diǎn)擊上傳按鈕時(shí)行為反應(yīng)
function upload() {
let file = fileEl.files[0];
if (file) {
let fileMD5;
// 利用時(shí)間換空間對(duì)文件首次進(jìn)行md5計(jì)算校驗(yàn)
hashFilePromise(file).then(md5 => {
let fetchList = [];
fileMD5 = md5;
// 遍歷文件切片生成fetch請(qǐng)求對(duì)象
ffeach(file).forEach(function (index, data) {
fetchList.push(fetchFile(uploadAddress, md5, index, data));
});
return Promise.all(fetchList);
}).then(function (result) {
// 當(dāng)所有數(shù)據(jù)片傳輸完畢后,執(zhí)行的內(nèi)容
const params = new URLSearchParams();
params.append('md5', fileMD5);
params.append('suffix', "png");
return fetch(mergeAddress, {
method: "POST",
body: params,
}).then(response => {
if (response.ok) {
return response.json();
}
throw Error("請(qǐng)求失敗");
});
}).then(result => {
// 當(dāng)碎片合并后返回信息
console.log(result);
});
// 清空input type=file中的文件內(nèi)容
fileEl.value = null;
} else {
alert("請(qǐng)選擇文件");
}
}