位置: IT常识 - 正文

Vue实现大文件分片上传,包括断点续传以及上传进度条(vue打包vendor文件过大)

编辑:rootadmin
Vue实现大文件分片上传,包括断点续传以及上传进度条 首先解释一下什么是分片上传

推荐整理分享Vue实现大文件分片上传,包括断点续传以及上传进度条(vue打包vendor文件过大),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:vue 大文件上传,vue实现大文件分块下载,vue大文件分段下载,vue大文件分段下载,vue实现大文件分块下载,vue 大文件上传解决方案,vue 大文件上传解决方案,vue大文件分段下载,内容如对您有帮助,希望把文章链接给更多的朋友!

        分片上传就是把一个大的文件分成若干块,一块一块的传输。这样做的好处可以减少重新上传的开销。比如:如果我们上传的文件是一个很大的文件,那么上传的时间应该会比较久,再加上网络不稳定各种因素的影响,很容易导致传输中断,用户除了重新上传文件外没有其他的办法,但是我们可以使用分片上传来解决这个问题。通过分片上传技术,如果网络传输中断,我们重新选择文件只需要传剩余的分片。而不需要重传整个文件,大大减少了重传的开销。

但是我们要如何选择一个合适的分片呢?因此我们要考虑如下几个事情:

1.分片越小,那么请求肯定越多,开销就越大。因此不能设置太小。

2.分片越大,灵活度就少了。

3.服务器端都会有个固定大小的接收Buffer。分片的大小最好是这个值的整数倍。

分片上传的步骤Vue实现大文件分片上传,包括断点续传以及上传进度条(vue打包vendor文件过大)

1.先对文件进行md5加密。使用md5加密的优点是:可以对文件进行唯一标识,同样可以为后台进行文件完整性校验进行比对。

2.拿到md5值以后,服务器端查询下该文件是否已经上传过,如果已经上传过的话,就不用重新再上传。

3.对大文件进行分片。比如一个100M的文件,我们一个分片是5M的话,那么这个文件可以分20次上传。

4.向后台请求接口,接口里的数据就是我们已经上传过的文件块。(注意:为什么要发这个请求?就是为了能断点续传,比如我们使用百度网盘对吧,网盘里面有续传功能,当一个文件传到一半的时候,突然想下班不想上传了,那么服务器就应该记住我之前上传过的文件块,当我打开电脑重新上传的时候,那么它应该跳过我之前已经上传的文件块。再上传后续的块)。

5.开始对未上传过的文件块进行上传。(这个是第二个请求,会把所有的分片合并,然后上传请求)。

6.上传成功后,服务器会进行文件合并。最后完成。

话不多说,直接开始干代码<template> <div> <!-- on-preview点击文件列表中已上传的文件时的钩子 --> <!-- http-request覆盖默认的上传行为,可以自定义上传的实现 --> <!-- limit最大允许上传个数 --> <!-- before-upload上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。 --> <!-- accept接受上传的文件类型(thumbnail-mode 模式下此参数无效) --> <!-- multiple是否支持多选文件 --> <!-- on-change文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用 --> <!-- on-remove文件列表移除文件时的钩子 --> <!-- file-list上传的文件列表, 例如: [{name: 'food.jpg', url: ''}] --> <!-- on-exceed文件超出个数限制时的钩子 --> <!-- auto-upload是否在选取文件后立即进行上传 --> <!-- action必选参数,上传的地址 例如 action="https://jsonplaceholder.typicode.com/posts/"--> <el-upload drag multiple :auto-upload="true" :http-request="checkedFile" :before-remove="removeFile" :limit="10" action="/tools/upload_test/" > <i class="el-icon-upload"></i> <div class="el-upload__text"> 将文件拖到此处,或 <em>点击上传</em> </div> </el-upload> <el-progress type="circle" :percentage="progress" class="progress" v-if="showProgress"></el-progress></div></template>

文件上传时,会走http-request方法,如果定义了这个方法,组件的submit方法就会被拦截掉(注意别在这个方法里面调用组件的submit 方法,会造成死循环),在这个方法里面我就可以搞我想搞的事情了。

http-request 这个传入的回调函数应该返回一个Promise,所以我自己定义了一个无用的Promise进去

const prom = new Promise((resolve, reject) => {})prom.abort = () => {}return prom如果要实现断点续传,需要和后端确定好,如何配合。

我这里的方案是,在我把所有的分片全部上传一遍后,会请求一个查询接口,后端在这个接口里面返回给我哪些分片没有上传成功(会给我序号),我这个时候,再去重新上传那些没有被上传成功的分片

直接贴完整代码,注释都在里面,看不懂的可以直接联系我,博客上有联系方式(依赖element-ui、axios、spark-md5)<template> <div> <!-- on-preview点击文件列表中已上传的文件时的钩子 --> <!-- http-request覆盖默认的上传行为,可以自定义上传的实现 --> <!-- limit最大允许上传个数 --> <!-- before-upload上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。 --> <!-- accept接受上传的文件类型(thumbnail-mode 模式下此参数无效) --> <!-- multiple是否支持多选文件 --> <!-- on-change文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用 --> <!-- on-remove文件列表移除文件时的钩子 --> <!-- file-list上传的文件列表, 例如: [{name: 'food.jpg', url: ''}] --> <!-- on-exceed文件超出个数限制时的钩子 --> <!-- auto-upload是否在选取文件后立即进行上传 --> <!-- action必选参数,上传的地址 例如 action="https://jsonplaceholder.typicode.com/posts/"--> <el-upload drag multiple :auto-upload="true" :http-request="checkedFile" :before-remove="removeFile" :limit="10" action="/tools/upload_test/" > <i class="el-icon-upload"></i> <div class="el-upload__text"> 将文件拖到此处,或 <em>点击上传</em> </div> </el-upload> <el-progress type="circle" :percentage="progress" class="progress" v-if="showProgress"></el-progress></div></template> <script>import axios from "axios";import SparkMD5 from "spark-md5";export default { data() { return { maxSize: 5 * 1024 * 1024 * 1024, // 上传最大文件限制 最小单位是b multiUploadSize: 100 * 1024 * 1024, // 大于这个大小的文件使用分块上传(后端可以支持断点续传) 100mb eachSize: 100 * 1024 * 1024, // 每块文件大小 100mb requestCancelQueue: [], // 请求方法队列(调用取消上传 url: "/tools/upload_test/", //上传进度 progress: 0, showProgress: false, // 每上传一块的进度 eachProgress: 0, // 总共有多少块。断点续传使用 chunksKeep:0, // 切割后的文件数组 fileChunksKeep:[], // 这个文件,断点续传 fileKeep:null }; }, mounted() { }, methods: { async checkedFile(options) { console.log(options); const { maxSize, multiUploadSize, getSize, splitUpload, singleUpload } = this; // 解构赋值 const { file, onProgress, onSuccess, onError } = options; // 解构赋值 if (file.size > maxSize) { return this.$message({ message: `您选择的文件大于${getSize(maxSize)}`, type: "error" }); } this.fileKeep = file const uploadFunc = file.size > multiUploadSize ? splitUpload : singleUpload; // 选择上传方式 try { await uploadFunc(file, onProgress); this.$message({ message: "上传成功", type: "success" }); this.showProgress = false; this.progress = 0; onSuccess(); } catch (e) { console.error(e); this.$message({ message: e.message, type: "error" }); this.showProgress = false; this.progress = 0; onError(); } const prom = new Promise((resolve, reject) => {}); // 上传后返回一个promise prom.abort = () => {}; return prom; }, // 格式化文件大小显示文字 getSize(size) { return size > 1024 ? size / 1024 > 1024 ? size / (1024 * 1024) > 1024 ? (size / (1024 * 1024 * 1024)).toFixed(2) + "GB" : (size / (1024 * 1024)).toFixed(2) + "MB" : (size / 1024).toFixed(2) + "KB" : size.toFixed(2) + "B"; }, // 单文件直接上传 async singleUpload(file, onProgress) { await this.postFile( { file, uid: file.uid, fileName: file.fileName ,chunk:0}, onProgress ); var spark = new SparkMD5.ArrayBuffer(); spark.append(file); var md5 = spark.end(); console.log(md5); const isValidate = await this.validateFile({ fileName: file.name, uid: file.uid, md5:md5, chunks:1 }); }, // 大文件分块上传 splitUpload(file, onProgress) { console.log('file11') console.log(file) return new Promise(async (resolve, reject) => { try { const { eachSize } = this; const chunks = Math.ceil(file.size / eachSize); this.chunksKeep = chunks const fileChunks = await this.splitFile(file, eachSize, chunks); this.fileChunksKeep = fileChunks console.log('fileChunks,文件数组切割后') console.log(fileChunks) //判断每上传一个文件,进度条涨多少,保留两位小数 this.eachProgress = parseInt(Math.floor(100 / chunks * 100) / 100); this.showProgress = true; let currentChunk = 0; for (let i = 0; i < fileChunks.length; i++) { // 服务端检测已经上传到第currentChunk块了,那就直接跳到第currentChunk块,实现断点续传 console.log(currentChunk, i); // 此时需要判断进度条 if (Number(currentChunk) === i) { // 每块上传完后则返回需要提交的下一块的index await this.postFile( { chunked: true, chunk: i, chunks, eachSize, fileName: file.name, fullSize: file.size, uid: file.uid, file: fileChunks[i] }, onProgress ); currentChunk++ // 上传完一块后,进度条增加 this.progress += this.eachProgress; // 不能超过100 this.progress = this.progress > 100 ? 100 : this.progress; } } var spark = new SparkMD5.ArrayBuffer(); spark.append(file); var md5 = spark.end(); console.log(md5); const isValidate = await this.validateFile({ chunks: fileChunks.length, // chunk: fileChunks.length, fileName: file.name, uid: file.uid, md5:md5, // task_id:file.uid }); // if (!isValidate) { // throw new Error("文件校验异常"); // } resolve(); } catch (e) { reject(e); } }); }, againSplitUpload(file, array) { console.log('file,array') console.log(file) console.log(array) return new Promise(async (resolve, reject) => { try { const { eachSize , fileKeep } = this; const chunks = this.chunksKeep const fileChunks = this.fileChunksKeep this.showProgress = true; // let currentChunk = 0; for (let i = 0; i < array.length; i++) { // 服务端检测已经上传到第currentChunk块了,那就直接跳到第currentChunk块,实现断点续传 // console.log(currentChunk, i); // 此时需要判断进度条 // 每块上传完后则返回需要提交的下一块的index await this.postFile( { chunked: true, chunk: array[i], chunks, fileName: file.fileName, fullSize: fileKeep.size, uid: file.uid, file: fileChunks[array[i]] }, ); // currentChunk++ // 上传完一块后,进度条增加 // this.progress += this.eachProgress; // 不能超过100 this.progress = this.progress > 100 ? 100 : this.progress; } var spark = new SparkMD5.ArrayBuffer(); spark.append(fileKeep); var md5 = spark.end(); console.log(md5); const isValidate = await this.validateFile({ chunks: fileChunks.length, // chunk: fileChunks.length, fileName: file.fileName, uid: file.uid, md5:md5, // task_id:file.uid }); // if (!isValidate) { // throw new Error("文件校验异常"); // } resolve(); } catch (e) { reject(e); } }); }, // 文件分块,利用Array.prototype.slice方法 splitFile(file, eachSize, chunks) { return new Promise((resolve, reject) => { try { setTimeout(() => { const fileChunk = []; for (let chunk = 0; chunks > 0; chunks--) { fileChunk.push(file.slice(chunk, chunk + eachSize)); chunk += eachSize; } resolve(fileChunk); }, 0); } catch (e) { console.error(e); reject(new Error("文件切块发生错误")); } }); }, removeFile(file) { this.requestCancelQueue[file.uid](); delete this.requestCancelQueue[file.uid]; return true; }, // 提交文件方法,将参数转换为FormData, 然后通过axios发起请求 postFile(param, onProgress) { console.log(param); const formData = new FormData(); // for (let p in param) { // formData.append(p, param[p]); // } formData.append('file', param.file) // 改了 formData.append('uid',param.uid) formData.append('chunk',param.chunk) const { requestCancelQueue } = this; const config = { cancelToken: new axios.CancelToken(function executor(cancel) { if (requestCancelQueue[param.uid]) { requestCancelQueue[param.uid](); delete requestCancelQueue[param.uid]; } requestCancelQueue[param.uid] = cancel; }), onUploadProgress: e => { if (param.chunked) { e.percent = Number( ( ((param.chunk * (param.eachSize - 1) + e.loaded) / param.fullSize) * 100 ).toFixed(2) ); } else { e.percent = Number(((e.loaded / e.total) * 100).toFixed(2)); } onProgress(e); } }; // return axios.post('/api/v1/tools/upload_test/', formData, config).then(rs => rs.data) return this.$http({ url: "/tools/upload_test/", method: "POST", data: formData // config }).then(rs => rs.data); }, // 文件校验方法 validateFile(file) { // return axios.post('/api/v1/tools/upload_test/', file).then(rs => rs.data) console.log(2) console.log(file) return this.$http({ url: "/tools/upload_test/upload_success/", method: "POST", data: file }).then(res => { if(res && res.status == 1){ this.againSplitUpload(file,res.data.error_file) return true } }); } }};</script><style scoped>.progress{ /* 在当前页面居中 */ position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); /* 宽度 */}</style>

更新代码,上面的代码使用md5加密后,与后端加密的MD5值不一样,下面的加密过后是一样的 

<template> <div :class="showProgress == true ? 'loading' : ''"> <!-- on-preview点击文件列表中已上传的文件时的钩子 --> <!-- http-request覆盖默认的上传行为,可以自定义上传的实现 --> <!-- limit最大允许上传个数 --> <!-- before-upload上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。 --> <!-- accept接受上传的文件类型(thumbnail-mode 模式下此参数无效) --> <!-- multiple是否支持多选文件 --> <!-- on-change文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用 --> <!-- on-remove文件列表移除文件时的钩子 --> <!-- file-list上传的文件列表, 例如: [{name: 'food.jpg', url: ''}] --> <!-- on-exceed文件超出个数限制时的钩子 --> <!-- auto-upload是否在选取文件后立即进行上传 --> <!-- action必选参数,上传的地址 例如 action="https://jsonplaceholder.typicode.com/posts/"--> <el-upload drag multiple :auto-upload="true" :http-request="checkedFile" :before-remove="removeFile" :limit="10" action="/tools/upload_chunk/" :disabled="showProgress"> <i class="el-icon-upload"></i> <div class="el-upload__text"> 将文件拖到此处,或 <em>点击上传</em> </div> </el-upload> <!-- 正在上传的弹窗 --> <el-dialog title="正在上传" :visible.sync="showProgress" width="50%"> <el-progress type="circle" :percentage="progress" class="progress" v-if="showProgress"></el-progress> </el-dialog> <!-- <el-progress type="circle" :percentage="progress" class="progress" v-if="showProgress"></el-progress> --> </div></template><script>import axios from "axios";import SparkMD5 from "spark-md5";export default { data() { return { maxSize: 5 * 1024 * 1024 * 1024, // 上传最大文件限制 最小单位是b multiUploadSize: 100 * 1024 * 1024, // 大于这个大小的文件使用分块上传(后端可以支持断点续传) 100mb eachSize: 100 * 1024 * 1024, // 每块文件大小 100mb requestCancelQueue: [], // 请求方法队列(调用取消上传 url: "/tools/upload_chunk/", //上传进度 progress: 0, showProgress: false, // 每上传一块的进度 eachProgress: 0, // 总共有多少块。断点续传使用 chunksKeep: 0, // 切割后的文件数组 fileChunksKeep: [], // 这个文件,断点续传 fileKeep: null, // 断点续传,文件md5 fileMd5Keep: "" }; }, mounted() { }, methods: { async checkedFile(options) { // console.log(options); const { maxSize, multiUploadSize, getSize, splitUpload, singleUpload } = this; // 解构赋值 const { file, onProgress, onSuccess, onError } = options; // 解构赋值 if (file.size > maxSize) { return this.$message({ message: `您选择的文件大于${getSize(maxSize)}`, type: "error" }); } this.fileKeep = file; const uploadFunc = file.size > multiUploadSize ? splitUpload : singleUpload; // 选择上传方式 try { await uploadFunc(file, onProgress); onSuccess(); } catch (e) { console.error(e); this.$message({ message: e.message, type: "error" }); this.showProgress = false; this.progress = 0; onError(); } const prom = new Promise((resolve, reject) => { }); // 上传后返回一个promise prom.abort = () => { }; return prom; }, // 格式化文件大小显示文字 getSize(size) { return size > 1024 ? size / 1024 > 1024 ? size / (1024 * 1024) > 1024 ? (size / (1024 * 1024 * 1024)).toFixed(2) + "GB" : (size / (1024 * 1024)).toFixed(2) + "MB" : (size / 1024).toFixed(2) + "KB" : size.toFixed(2) + "B"; }, // 单文件直接上传 async singleUpload(file, onProgress) { await this.postFile( { file, uid: file.uid, fileName: file.fileName, chunk: 0 }, onProgress ); // var spark = new SparkMD5.ArrayBuffer(); // spark.append(file); // var md5 = spark.end(); // console.log(md5); const reader = new FileReader(); reader.readAsArrayBuffer(file); let hashMd5 = ""; console.log(hashMd5); const that = this; function getHash(cb) { console.log("进入单个上传的getHash"); reader.onload = function (e) { console.log("进入单个上传的getHash的函数2"); console.log(hashMd5); console.log(this); // console.log(e) const hash = SparkMD5.ArrayBuffer.hash(e.target.result); // const hash = SparkMD5.ArrayBuffer.hash(file); console.log(hash); that.hashMd5 = hash; console.log(that.hashMd5); that.fileMd5Keep = hash; cb(hash); }; } await getHash(function (hash) { console.log(hash); console.log(that); // 请求接口 that.validateFile({ name: file.name, uid: file.uid, md5: hash, chunks: 1, filter_type: "user_data_file" }); }); }, // getMd5(file, chunkCount) { // const spark = new SparkMD5.ArrayBuffer(); // let currentChunk = 0; // const reader = new FileReader(); // reader.onload = function(e) { // spark.append(e.target.result); // currentChunk++; // if (currentChunk < chunkCount) { // console.log(currentChunk); // loadNext(); // } else { // console.log(spark.end()); // // 在这里请求接口 // return spark.end(); // } // }; // function loadNext() { // const start = currentChunk * chunkSize; // const end = // start + chunkSize >= file.size ? file.size : start + chunkSize; // reader.readAsArrayBuffer(file.slice(start, end)); // } // loadNext(); // }, // 大文件分块上传 splitUpload(file, onProgress) { return new Promise(async (resolve, reject) => { try { const { eachSize } = this; const chunks = Math.ceil(file.size / eachSize); this.chunksKeep = chunks; const fileChunks = await this.splitFile(file, eachSize, chunks); this.fileChunksKeep = fileChunks; console.log("fileChunks,文件数组切割后"); console.log(fileChunks); //判断每上传一个文件,进度条涨多少,保留两位小数 this.eachProgress = parseInt(Math.floor((100 / chunks) * 100) / 100); this.showProgress = true; let currentChunk = 0; for (let i = 0; i < fileChunks.length; i++) { // 服务端检测已经上传到第currentChunk块了,那就直接跳到第currentChunk块,实现断点续传 console.log(currentChunk, i); // 此时需要判断进度条 if (Number(currentChunk) === i) { // 每块上传完后则返回需要提交的下一块的index await this.postFile( { chunked: true, chunk: i, chunks, eachSize, fileName: file.name, fullSize: file.size, uid: file.uid, file: fileChunks[i] }, onProgress ); currentChunk++; // 上传完一块后,进度条增加 this.progress += this.eachProgress; // 不能超过100 this.progress = this.progress > 100 ? 100 : this.progress; } } // this.getMd5(file, chunks); // var spark = new SparkMD5.ArrayBuffer(); // spark.append(file); // var md5 = spark.end(); // console.log(md5); const spark = new SparkMD5.ArrayBuffer(); let currentChunkMd5 = 0; const that = this; const reader = new FileReader(); reader.onload = async function (e) { spark.append(e.target.result); currentChunkMd5++; if (currentChunkMd5 < chunks) { loadNext(); } else { // console.log(spark.end()); var hashMd5111 = spark.end(); that.fileMd5Keep = hashMd5111; console.log(that); console.log(hashMd5111); // 在这里请求接口 await that.validateFile({ name: file.name, uid: file.uid, md5: hashMd5111, chunks: fileChunks.length, filter_type: "git_secret_file" // chunk: fileChunks.length, }); } }; async function loadNext() { const start = currentChunkMd5 * eachSize; const end = start + eachSize >= file.size ? file.size : start + eachSize; await reader.readAsArrayBuffer(file.slice(start, end)); } this.$message({ message: "正在进行文件加密校验", type: "info" }); await loadNext(); // let hashMd5 = ""; // // console.log(hashMd5) // const that = this; // console.log("进入分片上传的getHash"); // function getHash(cb) { // reader.onload = function(e) { // console.log("进入分片上传的getHash的函数"); // const hash = SparkMD5.ArrayBuffer.hash(e.target.result); // // const hash = SparkMD5.ArrayBuffer.hash(file); // console.log(hash); // that.hashMd5 = hash; // console.log(that.hashMd5); // that.fileMd5Keep = hash; // cb(hash); // }; // reader.readAsArrayBuffer(file); // } // await getHash(function() { // console.log(that); // that.validateFile({ // name: file.name, // uid: file.uid, // md5: that.hashMd5, // chunks: fileChunks.length // // chunk: fileChunks.length, // }); // }); // 请求接口 // console.log('fileChunks.length') // 请求接口 // this.validateFile({ // fileName: file.name, // uid: file.uid, // md5:md5, // chunks:1 // }); resolve(); } catch (error) { reject(error); } }); }, // 断点续传 againSplitUpload(file, array) { console.log("file,array"); console.log(file); console.log(array); return new Promise(async (resolve, reject) => { try { const { eachSize, fileKeep } = this; const chunks = this.chunksKeep; const fileChunks = this.fileChunksKeep; this.showProgress = true; // let currentChunk = 0; for (let i = 0; i < array.length; i++) { // 服务端检测已经上传到第currentChunk块了,那就直接跳到第currentChunk块,实现断点续传 // console.log(currentChunk, i); // 此时需要判断进度条 // 每块上传完后则返回需要提交的下一块的index await this.postFile({ chunked: true, chunk: array[i], chunks, name: file.name, fullSize: fileKeep.size, uid: file.uid, file: fileChunks[array[i]] }); // currentChunk++ // 上传完一块后,进度条增加 // this.progress += this.eachProgress; // 不能超过100 this.progress = this.progress > 100 ? 100 : this.progress; } // var spark = new SparkMD5.ArrayBuffer(); // spark.append(fileKeep); // var md5 = spark.end(); // console.log(md5); var fileMd5KeepTwo = this.fileMd5Keep; const isValidate = await this.validateFile({ chunks: fileChunks.length, // chunk: fileChunks.length, name: file.name, uid: file.uid, md5: fileMd5KeepTwo, filter_type: "git_secret_file" // task_id:file.uid }); // if (!isValidate) { // throw new Error("文件校验异常"); // } // 关闭进度条 this.showProgress = false; // 重置进度条 this.progress = 0; resolve(); } catch (e) { reject(e); } }); }, // 文件分块,利用Array.prototype.slice方法 splitFile(file, eachSize, chunks) { return new Promise((resolve, reject) => { try { setTimeout(() => { const fileChunk = []; for (let chunk = 0; chunks > 0; chunks--) { fileChunk.push(file.slice(chunk, chunk + eachSize)); chunk += eachSize; } resolve(fileChunk); }, 0); } catch (e) { console.error(e); reject(new Error("文件切块发生错误")); } }); }, removeFile(file) { this.requestCancelQueue[file.uid](); delete this.requestCancelQueue[file.uid]; return true; }, // 提交文件方法,将参数转换为FormData, 然后通过axios发起请求 postFile(param, onProgress) { // console.log(param); const formData = new FormData(); // for (let p in param) { // formData.append(p, param[p]); // } formData.append("file", param.file); // 改了 formData.append("uid", param.uid); formData.append("chunk", param.chunk); formData.append("filter_type", "git_secret_file"); const { requestCancelQueue } = this; const config = { cancelToken: new axios.CancelToken(function executor(cancel) { if (requestCancelQueue[param.uid]) { requestCancelQueue[param.uid](); delete requestCancelQueue[param.uid]; } requestCancelQueue[param.uid] = cancel; }), onUploadProgress: e => { if (param.chunked) { e.percent = Number( ( ((param.chunk * (param.eachSize - 1) + e.loaded) / param.fullSize) * 100 ).toFixed(2) ); } else { e.percent = Number(((e.loaded / e.total) * 100).toFixed(2)); } onProgress(e); } }; // return axios.post('/api/v1/tools/upload_chunk/', formData, config).then(rs => rs.data) return this.$http({ url: "/tools/upload_chunk/", method: "POST", data: formData // config }).then(rs => rs.data); }, // 文件校验方法 validateFile(file) { // return axios.post('/api/v1/tools/upload_chunk/', file).then(rs => rs.data) return this.$http({ url: "/tools/upload_chunk/upload_success/", method: "POST", data: file }).then(res => { if (res && res.status == 1) { this.againSplitUpload(file, res.data.error_file); this.$message({ message: "有文件上传失败,正在重新上传", type: "warning" }); } else if (res && res.status == 0) { this.$message({ message: "上传成功", type: "success" }); this.showProgress = false; this.progress = 0; } else if (res && res.status == 40008) { this.$message.error(res.message); this.showProgress = false; this.progress = 0; } }); } }};</script><style scoped>.loading { /* 整体页面置灰 */ /* background: rgba(0, 0, 0, 0.5); */}.progress { /* 在当前页面居中 */ position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); margin-top: 40px; /* 宽度 */}/deep/ .el-dialog { position: relative; height: 500px;}</style>
本文链接地址:https://www.jiuchutong.com/zhishi/283945.html 转载请保留说明!

上一篇:gfxacc.exe是什么进程 作用是什么 gfxacc进程查询(chcfg.exe是什么)

下一篇:tdw89741n增强型路由器无法获取获取PVC该怎么办(路由器增强型)

  • word怎么添加导航目录(word怎么添加导航链接)

    word怎么添加导航目录(word怎么添加导航链接)

  • 苹果x不开免提声音小(苹果X不开免提听不到声音)

    苹果x不开免提声音小(苹果X不开免提听不到声音)

  • iphone11用的什么基带(iPhone11用的什么马达)

    iphone11用的什么基带(iPhone11用的什么马达)

  • 苹果x设置面容时老是高一点低一点(苹果X设置面容一直低一点高一点)

    苹果x设置面容时老是高一点低一点(苹果X设置面容一直低一点高一点)

  • 微信里公众号怎么找(微信里公众号怎么关注电子证)

    微信里公众号怎么找(微信里公众号怎么关注电子证)

  • 饿了么食物id是什么意思(饿了么id在哪里找)

    饿了么食物id是什么意思(饿了么id在哪里找)

  • airpods2无线充电盒和有线有什么区别(airpods2无线充电盒怎么充电)

    airpods2无线充电盒和有线有什么区别(airpods2无线充电盒怎么充电)

  • 12306什么叫添加受让人(12306添加成员在哪里)

    12306什么叫添加受让人(12306添加成员在哪里)

  • 在手机上怎么退出在电脑上登录QQ(在手机上怎么退流量包)

    在手机上怎么退出在电脑上登录QQ(在手机上怎么退流量包)

  • 打印机显示e3怎么解决(打印机显示e3怎么解决 打印机显示e3解决方法介绍)

    打印机显示e3怎么解决(打印机显示e3怎么解决 打印机显示e3解决方法介绍)

  • 一个路由器可以连接多少手机(一个路由器可以接两条宽带吗?)

    一个路由器可以连接多少手机(一个路由器可以接两条宽带吗?)

  • 微信位置显示路线没了(微信位置显示路线怎么设置)

    微信位置显示路线没了(微信位置显示路线怎么设置)

  • 京享值变150还能恢复么(京享值会降低吗)

    京享值变150还能恢复么(京享值会降低吗)

  • 运算器可以进行什么(运算器可以进行哪两种运算)

    运算器可以进行什么(运算器可以进行哪两种运算)

  • 拼多多店铺编号怎么查(拼多多店铺编号在哪里)

    拼多多店铺编号怎么查(拼多多店铺编号在哪里)

  • 小红书苹果手机怎么不能下载(小红书苹果手机不能用)

    小红书苹果手机怎么不能下载(小红书苹果手机不能用)

  • apple官网购买放心吗(苹果官网下单有保障吗)

    apple官网购买放心吗(苹果官网下单有保障吗)

  • lndtl40什么型号(华为lndtl40什么型号手机)

    lndtl40什么型号(华为lndtl40什么型号手机)

  • 导航怎么设置货车限行(导航怎么设置货车,小车通用)

    导航怎么设置货车限行(导航怎么设置货车,小车通用)

  • 苹果浏览器最近访问记录怎么删除(苹果浏览器最近关闭的标签页)

    苹果浏览器最近访问记录怎么删除(苹果浏览器最近关闭的标签页)

  • 已激活的Office因激活问题无法使用(office已经激活)

    已激活的Office因激活问题无法使用(office已经激活)

  • 在Linux中安装是使用系统性能监控软件Nmon(linux安装方式有)

    在Linux中安装是使用系统性能监控软件Nmon(linux安装方式有)

  • python Web开发 flask轻量级Web框架实战项目--实现功能--账号密码登录界面(连接数据库Mysql)(python web开发方向的第三方库有哪些)

    python Web开发 flask轻量级Web框架实战项目--实现功能--账号密码登录界面(连接数据库Mysql)(python web开发方向的第三方库有哪些)

  • 纳税怎么理解
  • 会计所得税分录?
  • 有限责任公司的股东人数为多少
  • 小规模申报增值税怎么申报
  • 补交以前年度车船税
  • 财务发票报销时限是多久
  • 已交的增值税能计入费用吗
  • 货物和运费一起开票怎么开
  • 资产负债表的其他应付款怎么填列
  • 收到生育津贴会计分录怎么做
  • 核算会计科目职工薪酬的范围
  • 税务系统有问题
  • 税收和税法是什么关系
  • 长期待摊费用摊销表
  • 个税手续费返还计入哪个科目
  • 股票红利税如何征收
  • 有形动产租赁印花税税率是多少
  • 房地产公司需要和哪些部门打交道
  • 返回的工会经费如何做账最新
  • 企业购买自行车记账什么科目
  • 进口税退税
  • 老板垫付款做会计分录
  • 进项已抵扣发票作废账务处理
  • php遍历显示多维数组
  • 做胃镜多少钱了
  • 利息支出属于生产成本吗
  • u盘突然被写保护是坏了吗
  • php笔记程序
  • 银装素裹的意思和造句
  • 海浪冲击着海岸
  • 企业合并一般债权怎么算
  • .net tpl
  • php输出空格语句
  • 小规模纳税人什么意思
  • 异地工作人员管理
  • 个人工程款结算了对方不付怎么办
  • vue 同局域网访问不到的问题及解决
  • 私募基金成立的规模条件
  • 逆回购划算吗
  • 购买原材料运输费的增值税计入什么科目
  • 固定资产科目代码是多少
  • 企业所得税期间费用明细表
  • 基本户和零余额可以是一个账号么
  • 生成100个[30-99]之内的随机数
  • 单位卖车怎么做账
  • 应交税费属于什么负债
  • 固定资产支付的保险费计入成本吗
  • 劳务派遣公司账务
  • 关于消费税的会计处理
  • 提前还贷款要满十八岁吗
  • 注册公司好麻烦
  • 中央空调的维护费一年要多少钱?
  • 企业大额融资需要什么资料
  • 全资子公司合并报表编制
  • sql server使用
  • windows mobile应用下载
  • 英文版西游记
  • 巧用护手霜保养皮衣
  • wp8.1怎么升级wp10
  • 将程序桌面图标放到桌面
  • winxp中网桥Bridge功能概述及配置注意事项
  • linux 修复系统
  • centos禁止ip访问
  • windows7旗舰版桌面壁纸怎么更换
  • win10系统如何查看版本号
  • linuxshadow破解
  • win7系统开机黑屏如何处理
  • linux查看系统配置内存大小
  • onkeyup,onkeydown和onkeypress的区别介绍
  • 编写批处理
  • 菜鸟 javascript
  • android 安卓开发 openssl
  • jquery动态添加元素
  • python爬虫有道翻译
  • python定制函数
  • 出口退税需要哪些
  • 如何提升基层党建质量
  • 腾讯 短信服务
  • 加强党的作风建设是目前全党的中心
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设