完整代码示例,功能和需求不同切勿直接复制使用。只完成了切片上传和进度条,合并文件是后端自动合并的没有通知后端合并,也没有弄断点续传功能。 这里就会遇到打印FormData对象打印不出来可以参考我另一个关于打印FormData对象的文章。
<template>
<div class="myDiv">
<el-upload class="upload-demo" :on-change="uploadFile" :on-exceed='changeFile' :show-file-list="false" :auto-upload="false" ref="uploadfile" :limit="1">
<el-button size="small" type="primary" :loading="loadingFile">上传文件</el-button>
</el-upload>
<ul v-if="fileList.length >0" class="ulBox">
<li v-for="(item,i) in fileList" :key="i"><span>{{item.name}}</span>
<Delete class="myicon" @click="del(item.url,item.id)" style="width: 1em; height: 16px; margin-left: 8px" />
</li>
</ul>
<el-progress v-if="progress" :percentage="percentage"></el-progress>
</div>
</template>
<script>
import SparkMD5 from "spark-md5";
import { ElMessage } from 'element-plus'; //引入elementui消息提示框
export default {
components: {},
props: ['file'],
data() {
return {
progress: false, //是否显示进度条
percentage: 0, //进度条
fileList: [], //文件回显
loadingFile: false, //这个变量没有用
uploadUrl:'http://192.168.101.166:11415/',
}
},
watch: {
file(a) {
if (a) {
this.fileList = [{
name: this.file,
id: this.makeRandom(1, 1000),
url: this.file
}];
}
}
},
created(){},
mounted(){
if (this.file) {
this.fileList = [{
name: this.file,
id: this.makeRandom(1, 1000),
url: this.file
}];
}
},
methods: {
changeFile() {
ElMessage.warning('只能上传1个文件')
},
del(url, id) {
this.fileList.forEach((item, index) => {
console.log(id, item.id)
if (item.id == id) {
this.fileList.splice(index, 1);
ElMessage.success('文件已经删除');
let mes = {
file: null,
size: null
}
this.$emit('getFileList', mes)
}
})
},
async uploadFile(e) {
let file = e.raw;
let that = this;
const chunkSize = 10 * 1024 * 1024; //定义分片的大小 暂定为10M,方便测试
const fileSize = file.size;
const mineType = file.type;
// this.streamingFile(file);
// return
const fileMd5 = await that.getFileMd5(file);
const fileName = file.name;
// 判断文件大小小于10M直接传否则分片
if (fileSize <= chunkSize) {
let formdata = new FormData();
formdata.append('path', '/');
formdata.append('name', file.name);
formdata.append('md5', fileMd5);
formdata.append('file', file);
formdata.append('chunkFileSize', chunkSize)
formdata.append('size', fileSize)
formdata.append('mode', 'RANDOM')
formdata.append('respond', null)
await this.api.apiCopyfileuploadFile(formdata, that.uploadUrl).then((res) => {
if (res) {
this.fileList.push({
name: res.path,
id: this.makeRandom(1, 1000),
url: res.path
});
}
})
} else {
let oldformdata = new FormData();
oldformdata.append('path', '/');
oldformdata.append('md5', fileMd5);
let theFirstFile = e.raw.slice(0, chunkSize);
oldformdata.append('file', theFirstFile);
await this.api.apiCopyfileaddgetChunk(oldformdata,that.uploadUrl).then((res)=>{
console.log(res)
})
this.progress = true; //展示进度条
const chunkCount = Math.ceil(fileSize / chunkSize)
for (var i = 0; i < chunkCount; i++) {
//分片开始位置
let start = i * chunkSize
//分片结束位置
let end = Math.min(fileSize, start + chunkSize)
let _chunkFile = e.raw.slice(start, end)
let formdata = new FormData();
formdata.append('path', '/');
formdata.append('name', file.name);
formdata.append('md5', fileMd5);
formdata.append('chunks', chunkCount)
formdata.append('chunk', i)
formdata.append('file', _chunkFile);
formdata.append('chunkFileSize', chunkSize)
formdata.append('size', fileSize)
formdata.append('mode', 'RANDOM')
formdata.append('respond', null)
await this.api.apiCopyfileuploadFile(formdata, that.uploadUrl).then((res) => {
if (res) {
//进度条
this.percentage = (((i + 1) / chunkCount) * 100).toFixed(0) | 0;
// 判断是最后一个
if (i == chunkCount - 1) {
this.fileList.push({
name: res.path,
id: this.makeRandom(1, 1000),
url: res.path
});
}
}
})
}
}
this.$refs.uploadfile.value = null;
this.progress = false;
let mes = {
file: this.fileList[0].url,
size: fileSize
}
this.$emit('getFileList', mes)
ElMessage.success('文件上传成功')
},
/**
* 请求后端合并文件
* @param fileMd5 文件md5
* @param fileName 文件名称
* @param count 文件分片总数
*/
async composeFile(fileMd5) {
console.log("开始请求后端合并文件")
let data = {
md5: fileMd5,
// suffix:fileName
}
let url = `http://192.168.101.4:11415/`
await this.api.apiCopyfileaddSuffix(data, url).then((res) => {
if (res.success) {
console.log(res.data)
}
})
},
// 流式传输文件
streamingFile(file) {
// let myFs=require('fs');
// let readFile=myFs.createReadStream(file);
// readFile.once('open',function(){
// console.log('可读流打开了');
// });
// readFile.once('close',function(){
// console.log('可读流关闭了');
// // ws.end();
// });
// readFile.on('data',function(data){
// console.log(data)
// // ws.write(data);
// });
},
getFileMd5(file) {
console.log('file', file);
let fileReader = new FileReader()
fileReader.readAsArrayBuffer(file);
console.log(fileReader)
let spark = new SparkMD5()
return new Promise((resolve) => {
fileReader.onload = (e) => {
spark.appendBinary(e.target.result)
resolve(spark.end())
}
})
},
},
}
</script>
<style lang="less" scoped>
.myDiv{ width: 100%;}
.ulBox{
li{display: flex; align-items:center; cursor: pointer;
&:hover{ background: #f1f1f1; }
.myicon{
&:hover{ color: #409eff;}
}
}
}
</style>