所用技术栈
- JavaScript
- python
- tornado
- madtornado
该文所用到的一切资源
注意事项
- 本文封装的upload.js没有完全耦合后端的madtornado进行实现,但是结合madtornado接口方案可以更加便利完成分片上传任务
- 本文后端使用的python+tornado的结合,但是tornado并非原生tornado而是被封装后的madtornado,madtornado让tornado使用起来更加简单,但是使用者需要有tornado使用经验,并结合madtornado文档才能充分使用
前端实现
upload.js接口说明
ffeach() 创建FileForeach对象工厂函数
参数: file(必填) File对象
参数: chunkSize(选填) 单个文件块大小,单位bytesnew FileForeach() 文件分块函数,主要用于文件提取分割后的数据块
参数: file(必填) File对象
参数: chunkSize(选填) 单个文件块大小,单位bytesFileForeach#isOutRange() 判断文件是否超出可提取的大小
FileForeach#nextLoad() 获取下一个文件块,返回Blob对象
FileForeach#forEach() 遍历File对象切割的文件块
参数: callback(必填) 回调函数,接收一个blob对象为文件数据块
注意:当数据块被遍历完毕后,将无法再产出文件块,FileForeach不保存任何数据块,为了节省空间
如果需要二次遍历,需要重新创建FileForeach对象
hashFile() 对文件进行hash运算,该方法异步执行
参数: file(必填) File对象
参数: callback(选填) 接收运算完的hash结果值函数
参数: chunkSize(选填) 单个文件块大小,单位byteshashFilePromise() 对文件进行hash运算,该方法异步执行,并且会返回Promise对象
参数: file(必填) File对象
参数: chunkSize(选填) 单个文件块大小,单位bytesfetchFile() 上传文件块
参数: address(必填) URL请求地址
参数: md5(必填) 文件md5值
参数: block(必填) 当前文件块的索引
参数: data(必填) 文件块数据
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";
// 点击上传按钮时行为反应
function upload() {
let file = fileEl.files[0];
if (file) {
let fileMD5;
// 利用时间换空间对文件首次进行md5计算校验
hashFilePromise(file).then(md5 => {
let fetchList = [];
fileMD5 = md5;
// 遍历文件切片生成fetch请求对象
ffeach(file).forEach(function (index, data) {
fetchList.push(fetchFile(uploadAddress, md5, index, data));
});
return Promise.all(fetchList);
}).then(function (result) {
// 当所有数据片传输完毕后,执行的内容
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("请求失败");
});
}).then(result => {
// 当碎片合并后返回信息
console.log(result);
});
// 清空input type=file中的文件内容
fileEl.value = null;
} else {
alert("请选择文件");
}
}