大文件分片上传并发
我这边使用的是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();}})
}
相关文章:
大文件分片上传并发
我这边使用的是boostrap-fileimput 初始化文件上传框 $(document).ready(function () {$("#file-upload_import").fileinput({uploadUrl: "#",language: "zh", //设置语言showPreview: true,autoReplace: true,// uploadUrl: "/uact/uploa…...
数据结构——基于顺序表实现通讯录
一、. 基于动态顺序表实现通讯录 1.1 功能要求 1)⾄少能够存储100个⼈的通讯信息 2)能够保存⽤⼾信息:名字、性别、年龄、电话、地址等 3)增加联系⼈信息 4)删除指定联系⼈ 5)查找制定联系⼈ 6&…...
行业追踪,2023-11-03
自动复盘 2023-11-03 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…...
JSPv2之El
(一)EL的基本语法 1优点 1 jsp的java太长了,el自己的语言${ 开始 }结束 2el直接返回空字符转,而java直接报错 3使用“lt”代替“<”运算符,如果运算符后面是数字,在运算符 *EL取值时,没有数组的下标越界,没有…...
出现 gpg: cancelled by user时的处理方法
今天在使用git commit -S -m "comment" check in 代码的时候, 莫名其妙出现了以下错误: gpg: cancelled by user经过在网上查询资料, 本质原因是GnuPG没有$(tty)的读写权限,有以下两种解决方法是靠谱的: c…...
MySQL中表的增删改查
目录 一、CRUD 二、新增(Create) (1)语法 (2)单行数据全列插入 (3)多行数据指定列插入 三、查询(Retrieve) (1)语法 …...
web.py python服务器两种模板template使用方法
【版权声明】 本文为博主原创文章,未经博主允许严禁转载,我们会定期进行侵权检索。 更多python应用或算法总结请关注我的博客:https://blog.csdn.net/suiyingy,或”乐乐感知学堂“公众号。 web.py是Python Web框架之一,…...
Flutter 01 目录结构入门
一、Flutter目录结构: 二、Flutter入口文件、入口方法: 三、Flutter Demo: demo1: import package:flutter/material.dart;//MaterialApp 和 Scaffold两个组件装饰App void main() {runApp(MaterialApp(home: Scaffold(appBar: A…...
Esxi安装OpenWrt
最近折腾下软路由主要就是实现局域网内的上网。 1.StarWind V2V Converter下载 先去下载个StarWind V2V Converter,觉得麻烦我在网上有找到一个博主的地址点击这里。 这是官网地址传送门,然后一阵乱输入点击下载 然后 双击之后无脑下一步即可。 2.Op…...
tuple 简易实现(C++ 模板元编程)
std::tuple 在标准库里面,tuple主要有下面四个类模板 or 函数模板 tupletuple_sizetuple_elementget 在后续有实现:tuple_size_v tuple_size::value和tuple_element_t tuple_element::type。 事例Example: auto tup std::tuple<in…...
Http代理与socks5代理有何区别?如何选择?(二)
上篇文章我们基本分别了解了http代理与socks5代理的定义与优缺点,接下来我们继续来了解http代理与socks5代理之间的比较与区别。 一、两者的比较 1、功能比较 HTTP代理专门用于Web流量,并在处理HTTP和HTTPS协议方面非常高效。它们可以修改正在传输的数…...
java中main方法和@Test注解的区别
Java的main方法和Test注解在用途和功能上有很大的区别。 main方法是Java应用程序的入口点。当你运行一个Java程序时,JVM会首先查找具有public static void main(String[] args)签名的类,并从这个方法开始执行程序。main方法通常用于控制程序的启动、执行…...
C++进阶语法——STL 标准模板库(下)(Standard Template Library)【学习笔记(七)】
文章目录 STL 代码示例1、迭代器2、算法3、array容器示例4、vector示例5、deque(double ended queue,双端数组)示例6、list(链表)容器7、set示例8、map示例9、stack 示例10、queue示例11、priority_queue (…...
力扣:求最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 示例1: 输入: strs ["flower", "flow" , "flight"] 输出: "fl" 示例2: 输入: strs ["dog","racecar","car&…...
Redis入门04-消息通知
目录 Redis中的消息通知 命令行操作 Redis中的管道 Redis中的消息通知 Redis可以用作消息队列的中间件,它提供了一种轻量级、高性能的消息传递机制,适用于实时通信、任务队列、事件处理等各种应用。以下是有关如何使用Redis作为消息队列的一些重要信…...
关于idea使用的一些操作设置
关于idea使用的一些操作设置 1. 常用的一下设置1.1 快捷键相关1.2 配置自动生成注释(类、方法等)1.3 maven项目相关1.4 常见其他的一些操作设置 2. IntelliJ IDEA 取消param注释中参数报错提示3. idea同时打开多个文件,导航栏不隐藏、自动换行…...
CLion 2023.2.2(C ++ IDE智能代码编辑器)
CLion 2023是一款跨平台C/C集成开发环境(IDE)。它为Mac用户提供了高效的编程体验,帮助程序员们在Mac平台上进行C/C开发。 CLion 2023支持多种编译器和调试器,并具有强大的代码分析和导航功能。它还为用户提供了许多便捷的工具和插…...
企业级API资产如何管理
在当今数字化时代,API已成为企业开发和创新的重要工具,如何高效地管理和调度这些资产成为了企业发展的重要课题。API资产管理的出现,为企业解决了这一难题,通过合理管理和利用API资产,企业可以更好地推动业务发展&…...
Git https方式拉的代码IDEA推送代码报错
报错信息 fatal: could not read Username for ‘https://codehub-cn-south-1.devcloud.huaweicloud.com’: No such file or directory 18:18:39.885: [recovery_pattern] git -c credential.helper -c core.quotepathfalse -c log.showSignaturefalse push --progress --porc…...
C++ capacity()用法总结
1. 容器的容量 容器的size是指它已经保存的元素的数目;而capacity则是在不分配新的内存空间的前提下它最多可以保存多少元素。capacity(),size(),reserve(),resize()这几个都是不太容易区分的函数 functionmeancapacity()获得容…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
Unity UGUI Button事件流程
场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...
