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

  • oppo手机怎么导入旧手机数据(oppo手机怎么导出通讯录联系人)

    oppo手机怎么导入旧手机数据(oppo手机怎么导出通讯录联系人)

  • win11怎么退出微软账户(WIN11怎么退出微软账号登录)

    win11怎么退出微软账户(WIN11怎么退出微软账号登录)

  • 微信怎样隐藏电话号码(微信怎样隐藏电话号码关了,为什么别人手机还看到)

    微信怎样隐藏电话号码(微信怎样隐藏电话号码关了,为什么别人手机还看到)

  • 抖音极速版怎么私聊作者(抖音极速版怎么赚钱 一天能赚多少)

    抖音极速版怎么私聊作者(抖音极速版怎么赚钱 一天能赚多少)

  • 闲鱼卖家发布于不同地方(闲鱼卖家发布于不同地方有影响吗)

    闲鱼卖家发布于不同地方(闲鱼卖家发布于不同地方有影响吗)

  • 支付宝收钱怎么添加员工(支付宝收钱怎么开通花呗收款)

    支付宝收钱怎么添加员工(支付宝收钱怎么开通花呗收款)

  • 抖音当前机型不支持此道具(抖音当前机型不支持)

    抖音当前机型不支持此道具(抖音当前机型不支持)

  • 微信群删了怎么恢复(微信群删了怎么恢复找回来)

    微信群删了怎么恢复(微信群删了怎么恢复找回来)

  • 苹果耳机充电盒后面那个按钮是什么(苹果耳机充电盒电量)

    苹果耳机充电盒后面那个按钮是什么(苹果耳机充电盒电量)

  • oppo是多少瓦快充(oppo快充功率)

    oppo是多少瓦快充(oppo快充功率)

  • 腾讯课堂有摄像头吗(腾讯课堂有摄像头功能吗)

    腾讯课堂有摄像头吗(腾讯课堂有摄像头功能吗)

  • 耳机dts音效是什么(dts2.0耳机)

    耳机dts音效是什么(dts2.0耳机)

  • 换手机了怎么把照片转过来(换手机了怎么把微信聊天记录弄到新手机)

    换手机了怎么把照片转过来(换手机了怎么把微信聊天记录弄到新手机)

  • 小米cc9e支持18瓦快充吗(小米cc9e最高支持多少w)

    小米cc9e支持18瓦快充吗(小米cc9e最高支持多少w)

  • 定位快捷键ctrl加什么(定位快捷键怎么用)

    定位快捷键ctrl加什么(定位快捷键怎么用)

  • photoshop是不是应用软件(photoshop属于应用软件嘛)

    photoshop是不是应用软件(photoshop属于应用软件嘛)

  • iphone8的默认铃声是什么(iphone8p默认铃声)

    iphone8的默认铃声是什么(iphone8p默认铃声)

  • 快手点赞为什么有限制(快手点赞为什么别人能看到)

    快手点赞为什么有限制(快手点赞为什么别人能看到)

  • 媒体声音突然没有声音了该怎么办(媒体声音突然没有声音了该怎么办OPPO)

    媒体声音突然没有声音了该怎么办(媒体声音突然没有声音了该怎么办OPPO)

  • qq2008在2014年还能用吗(2008版本qq)

    qq2008在2014年还能用吗(2008版本qq)

  • oppo手机如何关机(oppo手机如何关机重启手机)

    oppo手机如何关机(oppo手机如何关机重启手机)

  • 小米手环4和荣耀手环4对比(小米手环4荣耀手环4)

    小米手环4和荣耀手环4对比(小米手环4荣耀手环4)

  • 华为p30微信视频美颜怎么开(华为p30微信视频有美颜功能吗)

    华为p30微信视频美颜怎么开(华为p30微信视频有美颜功能吗)

  • oppofindx分内外屏吗(oppofindx内屏和外屏是一体的吗?)

    oppofindx分内外屏吗(oppofindx内屏和外屏是一体的吗?)

  • 美册怎么去水印(美册怎么去水印视频教程)

    美册怎么去水印(美册怎么去水印视频教程)

  • 华为p30通话背景怎么设置(华为p30通话背景图怎么换)

    华为p30通话背景怎么设置(华为p30通话背景图怎么换)

  • 〖大前端 - 基础入门三大核心之JS篇⑱〗- JavaScript的流程控制语句「break 和 continue语句」(大前端技术)

    〖大前端 - 基础入门三大核心之JS篇⑱〗- JavaScript的流程控制语句「break 和 continue语句」(大前端技术)

  • 减免税额和免税额一样吗
  • 固定资产出售净残值怎么处理
  • 金税盘服务费怎么抵扣税
  • 小规模升级一般纳税人需要多久
  • 已经认证的发票可以作废吗
  • 合并报表编制流程的准备工作
  • 总分机构汇算清缴成功后还需要填表什么报表
  • 税款追征期起算点 增值税重新计算
  • 自行研发无形资产暂时性差异
  • 暂估发票到账出入库单要填吗
  • 其他资本公积属于
  • 所有者权益科目编码
  • 发票开错导致不能按时入账该怎么处理呢?
  • 小规模纳税人公司注销流程及费用
  • 退税勾选后如何开红字
  • 价内税包括
  • 建筑企业甲供材税收筹划
  • 预充值发票可以列支吗?
  • 土地增值税计税依据
  • 使用权资产什么时候开始使用
  • 小规模纳税人注销需要查账吗
  • 小规模纳税人如何开专票
  • 王者荣耀通用铭文狩猎和隐匿
  • .exe文件怎么打不开
  • win10蓝牙怎么开ldac
  • mac快捷键是什么意思
  • 安全费用的适用范围
  • php的用处
  • 税控机维护费抵扣分录
  • vscode常用插件功能简介
  • 投资者投资企业项目的主要目的是
  • 预提的奖金能不能提前申报个税
  • 其他权益工具投资公允价值变动计入什么科目
  • 这年头不好混图片
  • thinkphp6多语言
  • php常用加密技术
  • php接收post
  • GCC strict aliasing – 嫉妒就是承认自己不如别人
  • 已申报未导入是什么情况
  • 金融企业往来支出是一级科目吗
  • 资产负债表和利润表的勾稽关系
  • 差旅费账务处理例子
  • 企业内部研发支持方案
  • 增值税一般纳税人企业对同属于增值税
  • 建设单位罚款
  • 行政事业单位资产报废账务处理
  • 企业清算是怎么做账的
  • 合并设立是什么意思
  • 独立核算分公司与总公司的账务处理
  • 其他应交款 其他应付款
  • 赞助支出属于什么科目
  • 汇算清缴水电费没有发票填在哪里
  • 工程施工企业收到工程款,怎么做分录
  • 内部产生的商誉应确认为无形资产
  • 银行存款的收付应严格执行()的规定
  • 银行扣的账户管理费属于什么科目
  • 损益表格式 最新
  • 我国开征股票交什么税
  • 建筑企业其他业务收入范围
  • sql server多表查询
  • vs2008如何使用
  • nmeo.exe是什么
  • win8不能启动
  • windows7英雄联盟老是崩溃
  • win7系统宽带连接651
  • win10升级补丁位置
  • win7怎么删除wifi已连接过的网络
  • win7账户不见了
  • js判断手机浏览器设置了电脑版浏览
  • 辅组什么词?
  • nvm-windows
  • javascript获取对象方法属性
  • 编写js代码要注意什么
  • js dom操作方法
  • JavaScript快速排序
  • 辽宁省国税局网站
  • 河南省地方税务局公告2017年第4号
  • 公司忘记报税了怎么补
  • 租房税费怎么算的
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设