个人网站可以做音乐吗,seo公司排名教程,昆明网站外包,南阳建设局网站说明
1. 把文件按大小1M分割成N份
2. 每次上传时#xff0c;告诉后台大文件的md5、当前第几份#xff08;从0开始#xff09;、总共几份
3. 并行上传#xff0c;前端同时开启5个请求进行传输增加速度
4. 上传失败或出错后#xff0c;继续上传下一份#xff0c;把出错的份…说明
1. 把文件按大小1M分割成N份
2. 每次上传时告诉后台大文件的md5、当前第几份从0开始、总共几份
3. 并行上传前端同时开启5个请求进行传输增加速度
4. 上传失败或出错后继续上传下一份把出错的份放在队尾如果一直出错则中断请求防止死循环
5. 后台接受文件后通过md5进行比对上次是否接受过此文件如果接受则跳过最后进行文件合并出来
6. 前端代码如下...
7. 查看源代码请点击在线演示地址先上htmlinput idfileInput typefile multiplemultiple name /ul idbox!-- lispan文件名/spanspan文件类型/spanspan文件大小/spanspan上传进度/spanspan总进度/spanspan操作/span/lilispan/spanspan/spanspan/spanspaniem/em/iiem/em/iiem/em/iiem/em/iiem/em/i/spanspaniem/em/i/spanspana hrefjavascript:;上传/aa hrefjavascript:;暂停/aa hrefjavascript:;删除/a/span/li --
/ul选择input时把文件信息写在页面上因为涉及到断点续传为保证文件的唯一性需要本地读取文件并对其进行md5fileInput.addEventListener(change, function() {var files this.files;if (files.length) {let str lispan文件名/spanspan文件类型/spanspan文件大小/spanspan上传进度/spanspan总进度/spanspan操作/span/li;for (var i 0; i files.length; i) {var file files[i];str lispan${file.name}/spanspan${file.type}/spanspan${formatByte(file.size)}/spanspaniem/em/iiem/em/iiem/em/iiem/em/iiem/em/i/spanspanib文件读取中/b/iiem/em/i/spanspan data-index${i}a data-control1 hrefjavascript:;上传/aa data-control2 hrefjavascript:;暂停/aa data-control3 hrefjavascript:;删除/a/span/li;}box.innerHTML str;readFilesStep(0); // 文件太大同步读取} else {box.innerHTML }
}, false);
同步读取文件操作function readFilesStep(i) {var files fileInput.files;if (!files[i]) {return}var oLi box.children[i 1];oLi.dataset.count Math.ceil(files[i].size / SIZE); // 总共多少份var readProgress oLi.children[4].children[0].children[0];var reader new FileReader();reader.readAsDataURL(files[i]);reader.onload function () {oLi.dataset.md5 md5(this.result);readProgress.innerHTML 文件读取完毕;readProgress.parentNode.className stop hide;readFilesStep(i 1);reader null;}reader.onerror function (e) {console.error(e);readProgress.innerHTML 文件读取失败请重新选择;readFilesStep(i 1);reader null;}
}
因为li是创建出现的对box进行事件委托box.addEventListener(click, function (ev) {var target ev.target;var control target.dataset.control;var index Number(target.parentNode.dataset.index);if (control 1) {// 上传uploadItem(index);} else if (control 2) {// 暂停pauseItem(index);} else if (control 3) {// 删除delItem(index);}
}, false);
上传代码如下var SIZE 1024 * 1024; // 切片大小
var FETCH_NUM 5; // 上传文件同时发起请求数
var FETCH_MAP {}; // 上传请求句柄取消请求用
var FETCH_POOL {}; // 每一个上传文件的份数function uploadItem(index) {var file fileInput.files[index];var oLi box.children[index 1];var isPlaying Number(oLi.dataset.playing) || 0;if (isPlaying) { return }oLi.dataset.playing 1;var fileMd5 oLi.dataset.md5;var count oLi.dataset.count;var lastLoaded Number(oLi.dataset.lastLoaded || 0);if (!fileMd5) {alert(请等待文件读取)} else {var maxErrorTimes 10; // 最大出错次数// 第一次点开始会进行创建if (!FETCH_POOL[fileMd5]) {FETCH_POOL[fileMd5] [];for (var i 0; i count; i) {FETCH_POOL[fileMd5][i] i;}}FETCH_MAP[fileMd5] [];for (var i 0; i FETCH_NUM; i) {FETCH_MAP[fileMd5][i] null;step(i)}function step(i) {var cur FETCH_POOL[fileMd5].shift();if (cur ! undefined) {FETCH_MAP[fileMd5][i] uploadStep({file: file, cur: cur, count: count, md5: fileMd5,progressCb: function(e) {var loaded lastLoaded e.loaded;setProgress(loaded);var progressItem (e.loaded / e.total * 100).toFixed(2) %;var oProgressItem oLi.children[3].children[i];oProgressItem.title progressItem;oProgressItem.children[0].style.width progressItem;if (progressItem 100.00%) {oProgressItem.className stop} else {oProgressItem.className }}, successCb: function(){lastLoaded SIZE;setProgress(lastLoaded, true);step(i);}, errorCb: function(status) {// 失败把当前份放在末尾继续下一步FETCH_POOL[fileMd5].push(cur);if (status 0) {// 手动取消 暂停} else if (maxErrorTimes--) {// 出错10次后不再上传防止进入死循环step(i);}}});}}function setProgress(loaded, isFinished) {var oProgress oLi.children[4].children[1];// 实际上传的数据大小 文件大小此处做修正处理if (loaded file.size) {if (isFinished) {loaded file.size;oProgress.className stop;} else {loaded file.size * 0.9999;}}oLi.children[2].innerHTML formatByte(loaded) / formatByte(file.size);var progress (loaded / file.size * 100).toFixed(2) %;var lastProgress oProgress.title || 0%;// 并行上传 此处可能是线路1的进度和线路2的进度比较,优先显示最大值progress parseFloat(lastProgress) parseFloat(progress) ? progress : lastProgress;// 总进度条oProgress.title progress;oProgress.children[0].style.width progress;if (isFinished) {oLi.dataset.lastLoaded loaded;}}}
}
分步上传代码function uploadStep(obj) {var file obj.file;var cur obj.cur;var fileMd5 obj.md5;var count obj.count;var progressCb obj.progressCb;var successCb obj.successCb;var errorCb obj.errorCb;var params new FormData();var filename file.name;var fileChunk file.slice(SIZE * cur, SIZE * (cur 1));params.append(md5, fileMd5);params.append(file, fileChunk);params.append(cur, cur);params.append(count, count);var xhr new XMLHttpRequest();xhr.onreadystatechange function () {if (xhr.readyState 4) {if (xhr.status 200) {successCb successCb(JSON.parse(xhr.responseText))} else {errorCb errorCb(xhr.status)}}}xhr.upload.onprogress function (e) {progressCb progressCb(e)}xhr.open(POST, /api/upload, true);xhr.send(params);return xhr;
}function formatByte(b) {var kb b / 1024;if (kb 1024) {var m kb / 1024;if (m 1024) {var g m / 1024;return g.toFixed(2) G;} else {return m.toFixed(2) M;}} else {return kb.toFixed(2) K;}
}
点击暂停时取消上个建立的XMLHttpRequest请求这里用FETCH_MAP[md5]进行标记function pauseItem(index) {var file fileInput.files[index];var oLi box.children[index 1];var isPlaying Number(oLi.dataset.playing) || 0;if (!isPlaying) { return }oLi.dataset.playing 0;var fileMd5 oLi.dataset.md5;for (var i 0; i FETCH_MAP[fileMd5].length; i) {if (FETCH_MAP[fileMd5][i]) {FETCH_MAP[fileMd5][i].abort();FETCH_MAP[fileMd5][i] null;}}
}
点击删除时取消上次请求并隐藏lifunction delItem(index) {var file fileInput.files[index];var oLi box.children[index 1];var fileMd5 oLi.dataset.md5;oLi.className hide;if (FETCH_MAP[fileMd5]) {for (var i 0; i FETCH_MAP[fileMd5].length; i) {if (FETCH_MAP[fileMd5][i]) {FETCH_MAP[fileMd5][i].abort();FETCH_MAP[fileMd5][i] null;}}}
}
效果图https://www.zhihu.com/video/1086059444886044672在线演示地址上传大文件Web Worker 真正的多线程上传待更新。。。