位置: 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该怎么办(路由器增强型)

  • 荣耀x10max和x10的区别是什么(荣耀x10max和x10对比配置)

    荣耀x10max和x10的区别是什么(荣耀x10max和x10对比配置)

  • 人人通空间密码忘了怎么办(人人通空间密码错误)

    人人通空间密码忘了怎么办(人人通空间密码错误)

  • qq删了评论对方知道吗(qq删了评论)

    qq删了评论对方知道吗(qq删了评论)

  • 输入当天日期应按什么(输入当天日期应按( ))

    输入当天日期应按什么(输入当天日期应按( ))

  • airpodspro一定要ios13吗(airpodspro一定要用原装充电器吗)

    airpodspro一定要ios13吗(airpodspro一定要用原装充电器吗)

  • 主板8+4只插8能开机吗(8+4主板两个必须插吗)

    主板8+4只插8能开机吗(8+4主板两个必须插吗)

  • iphone到哪一步算激活(iphone从几开始)

    iphone到哪一步算激活(iphone从几开始)

  • 苹果激活后显示充过电(苹果激活后显示未激活)

    苹果激活后显示充过电(苹果激活后显示未激活)

  • 老电脑很卡加内存条能解决吗(老电脑卡加内存条有用吗)

    老电脑很卡加内存条能解决吗(老电脑卡加内存条有用吗)

  • 多媒体的层次结构由什么构成(多媒体的层次结构有五层什么与用户有直接接口)

    多媒体的层次结构由什么构成(多媒体的层次结构有五层什么与用户有直接接口)

  • 整理数据的方式有(整理数据的主要方法有哪些)

    整理数据的方式有(整理数据的主要方法有哪些)

  • 抖音黄v可以置顶视频么(抖音个人黄v有什么好处)

    抖音黄v可以置顶视频么(抖音个人黄v有什么好处)

  • 笔记本机械硬盘怎么装(笔记本机械硬盘突然消失只剩固态)

    笔记本机械硬盘怎么装(笔记本机械硬盘突然消失只剩固态)

  • mt732ch a是什么版本(mt782za/a什么版本)

    mt732ch a是什么版本(mt782za/a什么版本)

  • vivo怎么设置专属铃声(vivo怎么设置专属充电提示音)

    vivo怎么设置专属铃声(vivo怎么设置专属充电提示音)

  • 米兔定位电话怎么打电话(米兔定位电话怎么重置)

    米兔定位电话怎么打电话(米兔定位电话怎么重置)

  • 电源开关0和1哪个是开(电源开关01哪个是开)

    电源开关0和1哪个是开(电源开关01哪个是开)

  • 线下支付送流量在哪看(线下支付送流量是真的吗)

    线下支付送流量在哪看(线下支付送流量是真的吗)

  • 手机uc私密相册在哪里(uc隐私相册怎么添加相册图片)

    手机uc私密相册在哪里(uc隐私相册怎么添加相册图片)

  • 网易考拉如何退货(网易考拉会员怎么退会员)

    网易考拉如何退货(网易考拉会员怎么退会员)

  • 快手隐私用户是啥意思(快手隐私用户是不是把你拉黑了)

    快手隐私用户是啥意思(快手隐私用户是不是把你拉黑了)

  • linux下卸载vmware产品的方法(linux 卸载vmware)

    linux下卸载vmware产品的方法(linux 卸载vmware)

  • iphone手机从手机卡导入通讯录的方法(苹果手机移动到新手机)

    iphone手机从手机卡导入通讯录的方法(苹果手机移动到新手机)

  • 个体工商户的纳税人类型怎么选
  • 原始凭证太多如何删除
  • 甲方给的工程奖项有哪些
  • 增值税专票丢了能补开吗
  • 员工报销没有发票怎么入账
  • 应付职工薪酬期末余额怎么算
  • 个税系统如何升级到最新版本
  • 如何申请免税
  • 债务重组损益的计算公式
  • 前年度库存商品少结转业务怎么处理?
  • 政府补贴转给其他公司
  • 年终奖可以分几次发吗?
  • 税收预测表怎么填写
  • 增值税进项税额在借方还是贷方
  • 成本费用包括哪些包括外购材料吗
  • 普票红冲后原件没有了怎么办
  • 限制性股票股利会计处理
  • 样品赠送要确认收入吗
  • 进项税额转出不交税款怎么处理
  • 支付保洁费用
  • 在建工程可以质押吗
  • 收购股权公司
  • 实收资本和注册资本的账务处理
  • 怎么激活win10密钥
  • 购入办公楼按多少折算
  • thinkphp获取数据库数据
  • linux服务器nfs安装
  • 佣金手续费开什么发票
  • 增值税专用发票抵扣期限
  • 进程program
  • 公司购买的大型安装设备什么时候转入固定资产
  • 图书发行流程
  • 母子公司吸收合并税务处理
  • 太平鸟的翅膀上有几道红羽毛
  • PHP array_key_exists检查键名或索引是否存在于数组中的实现方法
  • 哪些费用报销可以不用发票
  • frameworks
  • 认识数据库思维导图
  • web开发 python
  • web过滤器的常见应用
  • 省外的发票能入账吗
  • 工会经费怎么上缴
  • 微信公众号认证主体是什么意思
  • 公司员工抽奖活动
  • 保教费收入要交企业所得税吗
  • 停车费报销怎么说委婉
  • 织梦使用手册
  • 银行账户管理的直接责任人是共享中心核算会计
  • mysql 触发器
  • 出口企业为什么免税又退税
  • 进项税需要转出的分录
  • 轿车折旧年限为几年
  • 政府对企业提交的项目申请报告主要从等方面进行核准
  • 国债利息收入要征税吗
  • 企业缴纳印花税时需要
  • 车船费代交是什么意思
  • 免抵退账务处理流程
  • 小微企业取得的进项税能不能抵扣
  • 停车费发票能报餐饮费吗怎么开
  • 一般纳税人注销公司流程2023
  • MySQL数据库中把表中的一个字段重命名
  • msi安装错误代码2503
  • 电脑连接宽带时出错怎么办
  • macbook怎么修复磁盘
  • 苹果系统数据怎么清掉
  • win8使用教程和技能
  • 锁屏壁纸设置后不显示怎么办
  • Unity3D 事件
  • javascript html5摇一摇功能的实现
  • jquery弹出页面
  • nodejs npm package.json中文文档
  • android edittext被系统键盘遮挡
  • vue路由router
  • jquery课程总结
  • javascript简述
  • java 把对象存到数据库
  • python如何获取
  • android中fragment
  • 处理报废固定资产
  • 公司借款给员工是否合法
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设