实现前端断点续传功能
实现原理将文件切割成几份,一份份的上传,上传完毕,再通过接口告知后端将所有片段合并
// 模板
<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;
}
}
浙公网安备 33010602011771号