<template>
<div>
<el-dialog
title="上传视频"
:visible.sync="dialogVisible"
width="50%"
:before-close="handleClose">
<el-upload
class="upload-demo"
ref="upload"
:action="uploadUrl"
:before-upload="beforeUpload"
:on-progress="handleProgress"
:on-success="handleSuccess"
:on-error="handleError"
:auto-upload="false"
:file-list="fileList"
list-type="text">
<el-button size="small" type="primary">选取视频</el-button>
<div slot="tip" class="el-upload__tip">支持 mp4, avi, mov, wmv, flv 格式,最大不超过 2GB</div>
</el-upload>
<el-progress :percentage="uploadPercentage" style="margin-top: 15px;"></el-progress>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="startUpload">上 传</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
dialogVisible: false,
fileList: [],
uploadPercentage: 0,
chunkSize: 5 * 1024 * 1024, // 5MB
uploadUrl: 'https://your-backend.com/upload'
};
},
methods: {
beforeUpload(file) {
const allowedTypes = ['video/mp4', 'video/avi', 'video/quicktime', 'video/x-ms-wmv', 'video/x-flv'];
const isAllowedType = allowedTypes.includes(file.type);
const isLt2G = file.size / 1024 / 1024 / 1024 < 2;
if (!isAllowedType) {
this.$message.error('视频格式不支持!');
return false;
}
if (!isLt2G) {
this.$message.error('视频大小不能超过 2GB!');
return false;
}
// 分片处理逻辑
this.fileList = this.sliceFile(file);
return false; // 阻止默认的上传行为
},
sliceFile(file) {
const chunks = [];
const totalChunks = Math.ceil(file.size / this.chunkSize);
for (let i = 0; i < totalChunks; i++) {
const chunk = file.slice(i * this.chunkSize, (i + 1) * this.chunkSize);
chunks.push({ chunk, index: i, file });
}
return chunks;
},
async startUpload() {
for (const { chunk, index, file } of this.fileList) {
const formData = new FormData();
formData.append('file', chunk);
formData.append('index', index);
formData.append('fileName', file.name);
await this.uploadChunk(formData);
}
// 合并请求
await this.mergeChunks(this.fileList[0].file.name);
},
async uploadChunk(formData) {
try {
await this.$axios.post(this.uploadUrl, formData, {
onUploadProgress: (progressEvent) => {
this.uploadPercentage = Math.round((progressEvent.loaded / progressEvent.total) * 100);
}
});
} catch (error) {
console.error('Upload chunk error', error);
}
},
async mergeChunks(fileName) {
try {
await this.$axios.post(`${this.uploadUrl}/merge`, { fileName });
this.$message.success('上传成功');
this.dialogVisible = false;
this.fileList = [];
this.uploadPercentage = 0;
} catch (error) {
this.$message.error('合并文件失败');
console.error('Merge chunks error', error);
}
},
handleProgress(event, file, fileList) {
this.uploadPercentage = Math.round((event.loaded / event.total) * 100);
},
handleSuccess(response, file, fileList) {
this.$message.success('上传成功');
this.fileList = [];
this.uploadPercentage = 0;
this.dialogVisible = false;
},
handleError(err, file, fileList) {
this.$message.error('上传失败');
this.uploadPercentage = 0;
},
handleClose(done) {
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
},
openDialog() {
this.dialogVisible = true;
}
}
};
</script>
<style scoped>
.upload-demo {
margin-top: 10px;
}
</style>