实现原理将文件切割成几份,一份份的上传,上传完毕,再通过接口告知后端将所有片段合并
// 模板
<el-form-item label="请选择文件:" v-if="!processPercentage"> <div class="upload-button-box"> <input type="file" name="file" ref="input" accept=".tar.gz" @change="onChange" class="upload-button" /> <el-button size="small" type="primary">上传文件</el-button> <span v-if="form.file" style="margin-left: 15px">{{ this.form.file.name }}</span> <div class="tips">支持扩展名:.tar.gz</div> </div> </el-form-item>
// 引入依赖
import md5Hex from 'md5-hex'
// 定义数据
data () { return { form: { file: undefined }, rules: { }, processPercentage: 0, // 文件块大小 200M eachSize: 1024 * 1024 * 20, loading: { upload: false }, fileLength: 0, isBool: false, isError: false } },
// 实现方法
// 关闭弹框的方法 onClose (type = 'dismiss') { if(type === 'dismiss') { this.isBool = false; } this.$emit('closeDialog', { name: this.dialoagName, type }); },
onChange (e) { this.form.file = Array.from(e.target.files)[0]; }, // 开始上传 async onImport() { try { this.isError = false; this.loading.upload = true; // 将名字转成编码 this.form.file.uid = md5Hex(this.form.file.name); // 定义当前上传的索引 this.form.file.chunk = 0; // 分片大小要求100M以下的分片大小设置为5M,以上的设置为20M if(this.form.size > 1024 * 1024 * 100) { this.eachSize = 1024 * 1024 * 20 } else { this.eachSize = 1024 * 1024 * 5 } this.fileLength = Math.ceil(this.form.file.size / this.eachSize); // 检测文件是否存在 const { data } = await PackageImportService.getPackageImportUpload(this.form.file.uid); this.isBool = true; this.onUpload(this.form, data); } catch (error) { console.log(error) } }, // 合并分片 async packageImportMerge() { try { // 合并分片 this.processPercentage = 100; await PackageImportService.packageImportMerge( this.form.file.uid, this.fileLength, this.form.file.name, this.$route.params.appId, this.$route.params.planId ); this.$message.success(`程序包[${this.form.file.name}]导入成功`); this.onClose('confirm') } finally { this.loading.upload = false; } }, async onUpload({file}, chunk) { try { if(!this.isBool) return; // 当前字节 const blobFrom = file.chunk * this.eachSize; // 获取文件块的终止字节 const blobTo = (file.chunk + 1) * this.eachSize > file.size ? file.size : (file.chunk + 1) * this.eachSize; if (chunk) file.chunk = chunk; // 进度条数值 this.processPercentage = Number((blobTo / file.size * 100).toFixed(1)); // 合并分片 if (file.chunk === this.fileLength) { this.packageImportMerge() return; } // 检查断点续传的分片存在与否 const { data } = await PackageImportService.checkPackageImport(file.uid, file.chunk); // 片段存在跳过本次上传 if (data) { file.chunk++; this.onUpload({file: file}); return; } // 将分片数据上传 let formData = new FormData(); formData.set('file', file.slice(blobFrom, blobTo)); await PackageImportService.packageImport(file.uid, file.chunk, formData); file.chunk++; this.onUpload({file: file}); } catch (error) { this.loading.upload = false; this.isError = true; } }