当前位置: 首页 > news >正文

大文件分片上传并发

我这边使用的是boostrap-fileimput

初始化文件上传框


$(document).ready(function () {$("#file-upload_import").fileinput({uploadUrl: "#",language: "zh", //设置语言showPreview: true,autoReplace: true,// uploadUrl: "/uact/uploadfile", //上传的地址uploadExtraData: { type: "1012-0001" },allowedFileExtensions: ["json"], //接收的文件后缀,allowedPreviewTypes: ["image"], //可以预览的文件类型// initialPreviewAsData: File,// maxFileSize:10485760, //10GshowUpload: false,maxFileCount: 1,minFileCount: 1,previewTemplates: {generic: '<div class="file-preview-frame" id="{previewId}" data-fileindex="{fileindex}" data-template="{template}">\n' +'</div>\n'},dropZoneTitle: "请选择一个json文件上传",// validateInitialCount: true,// showCaption: true,fileActionSettings: {// 在预览窗口中为新选择的文件缩略图设置文件操作的对象配置showRemove: true, // 显示删除按钮showUpload: false, // 显示上传按钮showDownload: false, // 显示下载按钮showZoom: false, // 显示预览按钮showDrag: false, // 显示拖拽},});})

分片和重传

var succeed = 0;
var fail_parts = []async function progress(percent, $element) {var progressBarWidth = percent * $element.width() / 100;$element.find('div').animate({ width: progressBarWidth }, 500).html(percent + "% ");
}function updateProgress(percentage) {$('.progress .progress-bar').attr('data-transitiongoal', percentage).progressbar({ display_text: 'fill' });
}function generateUUID() {// 生成全局uuidvar d = new Date().getTime();if (window.performance && typeof window.performance.now === "function") {d += performance.now();}var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {var r = (d + Math.random() * 16) % 16 | 0;d = Math.floor(d / 16);return (c == "x" ? r : (r & 0x3) | 0x8).toString(16);},)return uuid;
}const form = document.getElementById('upload-form');
const fileInput = document.getElementById('file-upload_import');
form.addEventListener('submit', async (e) => {e.preventDefault();$("#upload").attr("disabled", "disabled");const file = fileInput.files[0];if (!file) {alert("至少选择一个文件")return}const chunkSize = 10 * 1024 * 1024; // 10MB 分片大小// const chunkSize = 1 * 1024; // 1KB 分片大小let upload_id = generateUUID()// 切割文件const chunks = [];let offset = 0;while (offset < file.size) {const chunk = file.slice(offset, offset + chunkSize);chunks.push(chunk);offset += chunkSize;}$('.progress .progress-bar').attr('data-transitiongoal', 0).progressbar({ display_text: 'fill' });// 逐个上传分片const urls = [];for (let i = 0; i < chunks.length; i++) {const formData = new FormData();formData.append('chunk', chunks[i]);formData.append("upload_id", upload_id)formData.append('index', i);formData.append('size', file.size)urls.push({url: "你的分片上传地址",param: formData})}try {concurRequest(urls, 6).then(ret => {setTimeout(() => {$(document).trigger('chunksUploaded', [fail_parts, chunks, upload_id]);}, 1000);})} catch (error) {console.log("分片上传错误:" + error.data[0].index)fail_parts.push(error.data[0]);}
});$(document).on('chunksUploaded', async function (event, fail_parts, chunks, upload_id) {// 重传失败分片if (fail_parts.length > 0) {let retry_urls = [];for (let ele of fail_parts) {const formData = new FormData();formData.append('chunk', chunks[ele.index]);formData.append("upload_id", ele.upload_id)formData.append('retry', true)formData.append('index', ele.index)retry_urls.push({url: "你的分片上传地址",param: formData})}try {concurRequest(retry_urls, 3).then(ret => {console.log("重传分片成功!",res);})} catch (error) {console.log("重传分片" + error.msg + ":" + part.index)}}setTimeout(() => {$("#upload").removeAttr("disabled");if (fail_parts.length == 0) {const formData = new FormData();formData.append('total_chunks', chunks.length);formData.append("upload_id", upload_id);$.ajax({url: '/mongodb/import/merge/',method: 'POST',data: formData,processData: false,contentType: false,success: function (data) {if (data.status === 0) {alert('文件上传成功!');}}})} else {alert('文件上传失败,请稍后重新上传');}}, 2000);})

并发方法

/**
* 并发请求
* @param {string[]} urls 待请求的url数组
* @param {number} maxNum 最大的并发数
*/
function concurRequest(urls, maxNum) {return new Promise(resolve => {if (urls.length === 0) {/* 先考虑边界问题 */resolve([]);return;}const results = [] //存储请求结果并返回let index = 0; //下一个请求的url下标let count = 0; //计算请求的数量async function request() {if (index === urls.length) {return;}const i = index;const url = urls[index].url;const res = urls[index].param;index++try {let ret = await fetch(url, {method: "POST",body: res,});results[i] = ret //不能用push,因为这样就会出现异步完成优先写入不符合要求。var percent = ((index / urls.length).toFixed(2)) * 100;updateProgress(percent);} catch (error) {results[i] = err} finally {count++if (count === urls.length) {resolve(results);}request();}}const times = Math.min(maxNum, urls.length);for (let i = 0; i < times; i++) {request();}})
}

相关文章:

  • Linux———— 运算命令
  • PyTorch入门学习(十):神经网络-非线性激活
  • QT之多个界面相互切换 (stackedWidget控件)
  • 基于 golang 从零到一实现时间轮算法 (一)
  • uniapp书写顶部选项卡代码详细例子
  • 在Spring中,教你一招优雅的获取国际化语言配置的方法
  • 接口测试 —— Jmeter读取数据库数据作测试参数
  • 运维人必知必会的10个问题,不知道的快来补课!
  • NEFU数字图像处理(3)图像分割
  • HarmonyOS开发:基于http开源一个网络请求库
  • 双热点机制结合。5+铜死亡+铁死亡相关基因生信思路
  • 求职中遇到的性格测试,你看不出来的陷阱
  • 【面试精选】00后卷王带你三天刷完软件测试面试八股文
  • 开源播放器GSYVideoPlayer的简单介绍及播放rtsp流的优化
  • Java零基础入门-注释
  • [rust! #004] [译] Rust 的内置 Traits, 使用场景, 方式, 和原因
  • [译]前端离线指南(上)
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • HTTP 简介
  • Java编程基础24——递归练习
  • Linux中的硬链接与软链接
  • swift基础之_对象 实例方法 对象方法。
  • WePY 在小程序性能调优上做出的探究
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 前端_面试
  • 前端学习笔记之观察者模式
  • 浅谈web中前端模板引擎的使用
  • 巧用 TypeScript (一)
  • 软件开发学习的5大技巧,你知道吗?
  • 通过npm或yarn自动生成vue组件
  • 优秀架构师必须掌握的架构思维
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • ​一些不规范的GTID使用场景
  • # .NET Framework中使用命名管道进行进程间通信
  • #!/usr/bin/python与#!/usr/bin/env python的区别
  • #laravel 通过手动安装依赖PHPExcel#
  • (13)Hive调优——动态分区导致的小文件问题
  • (LeetCode C++)盛最多水的容器
  • (poj1.2.1)1970(筛选法模拟)
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (一)认识微服务
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • (转)linux 命令大全
  • ./和../以及/和~之间的区别
  • .Family_物联网
  • .net 4.0发布后不能正常显示图片问题
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .net 打包工具_pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++才是王道
  • .NET 设计一套高性能的弱事件机制
  • .net程序集学习心得
  • .net快速开发框架源码分享
  • .net网站发布-允许更新此预编译站点
  • .net下的富文本编辑器FCKeditor的配置方法