pan 25fab1b4ee 1、发布工具新增关联工具展示
2、详情页面调整
3、先上传文件夹功能
2024-09-02 10:36:58 +08:00

465 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<el-upload class="upload-demo" ref="upload" action="#"
:before-upload="beforeUpload"
:on-change="onChange"
:on-remove="handleRemove"
:multiple="isMultiple"
:on-exceed="handleExceed"
:accept="acceptType"
:limit="limit"
:file-list="fileList"
:auto-upload="true"
:http-request="uploadFile"
show-file-list>
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<el-button size="small" type="primary" @click="handleUploadFile">
上传文件夹
</el-button>
<!-- 上传-->
<input v-show="false" ref="fileRef" id="fileFolder" type="file" @change="handleFolderUpload" webkitdirectory
multiple="multiple" />
<!-- <input v-show="false" type="file" ref="fileRef" webkitdirectory @change="handleFolderUpload">
<el-button slot="trigger" size="small" type="primary">选取文件夹</el-button>-->
</el-upload>
<div slot="tip" class="el-upload__tip">只能上传{{acceptType}}文件</div>
<div v-show="progressFlag" class="head-img">
<el-progress :text-inside="true" :stroke-width="14" :percentage="progressPercent" status="success"></el-progress>
</div>
</div>
</template>
<script>
import axios from 'axios'
import {
getToken
} from "@/utils/auth";
import JSZip from 'jszip'
export default {
props: {
uploadUrl: {
type: String,
required: true
},
// 是否多选
isMultiple: {
type: Boolean,
default() {
return false
}
},
// 文件类型
type: {
type: Array,
default() {
return []
}
},
//上传类型
acceptType: {
type: String,
required: true
},
// 上传数量
limit: {
type: Number,
default() {
return 1
}
},
// 文件
dataFile: {
type: [Object, Array, String],
default() {
return ''
}
},
},
data() {
return {
fileList: [],
progress: 0,
isUploading: false,
progressFlag: false, //进度条初始值隐藏
progressPercent: 0, //进度条初始值
partSize: 5 * 1024 * 1024,
};
},
watch: {
dataFile: {
handler(newValue, oldValue) {
if (newValue) {
this.fileList = Array.isArray(newValue) ? newValue : [newValue]
} else {
this.fileList = []
}
},
immediate: true
}
},
methods: {
// 上传前
beforeUpload(file) {
/* const fileType = file.type.toLowerCase()
console.info("fileType=======", fileType)
const typeFlag = this.type.some(item => {
return fileType.indexOf(item) != -1
})
if (!typeFlag) {
this.$message.error('上传类型有误,请重新上传')
return false
}*/
},
//文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用
onChange(file, fileList) {
this.fileList = fileList;
},
handleRemove(file, fileList) {
this.fileList = fileList;
},
handleExceed(files, fileList) {
this.$message.warning(
"最多之能上传"+ this.limit +"个附件"
);
},
async uploadFile({ data, file }) {
let self = this
//初始化参数
if (file.size < this.partSize) {
let formData = new FormData()
formData.append("file", file)
self.progressFlag = true;
axios({
url: self.uploadUrl,
method: 'post',
data: formData,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
onUploadProgress: progressEvent => {
// progressEvent.loaded:已上传文件大小
// progressEvent.total:被上传文件的总大小
//进度条
self.progressPercent = ((progressEvent.loaded / progressEvent.total) * 100) | 0;
}
}).then(res => {
setTimeout(() => {
if (res.data.code == 200 && self.progressPercent === 100) {
setTimeout(function () {
self.$message({
message: '上传成功!',
type: 'success',
duration: '2000'
});
self.progressFlag = false;
self.progressPercent = 0
self.handleResult(res,file);
}, 500);
} else {
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
}
}, 1000);
}).catch(error => {
console.error(error)
self.progressFlag = false;
self.progressPercent = 0
self.$refs.upload.clearFiles();
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
})
} else {
file._shardCount = Math.ceil(file.size / this.partSize) //总片数
file.uploaded = 0
let formData = new FormData()
formData.append('fileName', file.name)
let self = this
//大文件上传初始化,返回uploadId initUpload(formData)
axios({
url: process.env.VUE_APP_BASE_API + "/common/initUpload",
method: 'post',
data: formData,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
}).then(function (res) {
if (res.status == 200) {
//从第0块开始上传
file.uploadId = res.data.uploadId
file.objectKey = res.data
file.chunkId = 0
self.uploadByChunk(file)
} else {
this.progress--
self.$message.error(res.msg)
}
}).catch(error => {
self.progressPercent = 0
self.progressFlag = false;
console.error(error)
})
}
},
//分片上传大文件
uploadByChunk(file) {
this._start = file.chunkId * this.partSize
this._end = Math.min(file.size, this._start + this.partSize)//结束时总大小,和 开始的大小+之前的大小比较
let self = this
let fileData = file.slice(this._start, this._end)
//获取文件块MD5
let reader = new FileReader()
reader.readAsBinaryString(fileData)
let form1 = new FormData()//new一个form的实例可以进行键值对的添加
form1.append('chunkFile', fileData) //slice方法用于切出文件的一部分
form1.append('uploadId', file.uploadId)
form1.append('chunkId', (file.chunkId + 1).toString())
form1.append('shardCount', file._shardCount.toString()) //是否最后一片
self.progressFlag = true;
//上传大文件的Chunk 返回chunk的MD5 uploadChunk(form1)
axios({
url: process.env.VUE_APP_BASE_API + "/common/uploadChunk",
method: 'post',
data: form1,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
onUploadProgress: progressEvent => {
// progressEvent.loaded:已上传文件大小
// progressEvent.total:被上传文件的总大小
//进度条
self.progressPercent = ((progressEvent.loaded / progressEvent.total) * 100) | 0;
}
}).then(response => {
if (response.status == 200) {
//判断返回的MD5值是否一致一致继续传下一块否则重传本块这里目前前后端MD5一直不一致暂时先注释掉有时间了我再研究一下
// self.md5Str[index] === response.msg ||
if (true) {
// this.$message.success('第' + (index + 1).toString() + '块文件上传成功')
file.uploaded++
self.percentageSend(file)
//如果没上传完成,继续上传一下块
file.chunkId++
if (file.chunkId < file._shardCount) {
this.uploadByChunk(file)
}
} else {
//不一致,重新传本块
this.$message.success('第' + (file.chunkId + 1).toString() + '块文件上传不成功,重新上传')
this.uploadByChunk(file.chunkId)
}
} else {
//出错,跳出循环显示错误
this.progress--
this.$message.error(response.msg)
}
})
},
//接收上传的百分值回调
percentageSend(file) {
let self = this
let perNum = Math.floor((file.uploaded / file._shardCount) * 100)
this.progressPercent = perNum
//如果上传完成,合并文件
if (perNum === 100) {
let form2 = new FormData()//new一个form的实例可以进行键值对的添加
form2.append('uploadId', file.uploadId)
form2.append('fileName', file.name)
// 大文件上传完成后合并
// 返回文件访问的URL
axios({
url: process.env.VUE_APP_BASE_API + "/common/mergeFile",
method: 'post',
data: form2,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
}).then(res => {
if (res.status == 200) {
setTimeout(function () {
self.$message({
message: '上传成功!',
type: 'success',
duration: '2000'
});
self.progressFlag = false;
self.progressPercent = 0
self.handleResult(res,file);
}, 500);
} else {
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
}
})
}
},
resetData() {
this.progress = 0;
},
handleResult(res, file) {
let self = this
const data = {
fileName: file.name,
fileSize: file.size,
fileUrl: res.data.url,
filePath: res.data.filePath,
fileOldName: res.data.originalFilename,
fileNewName: res.data.newFileName,
suffixType: res.data.suffixType
}
console.info("data===========", data)
self.$emit("handleSuccess", data)
},
/** 清空文件 **/
clearFile(){
this.$refs.upload.clearFiles();
this.fileList = []
},
handleUploadFile() {
document.getElementById("fileFolder").value = null;
this.$refs.fileRef.dispatchEvent(new MouseEvent("click"));
},
async handleFolderUpload(event) {
let self = this;
const files = event.target.files;
this.fileslength = files.length;
// 获取文件夹名称
let folderName = "";
if (files.length > 0) {
let relativePath = files[0].webkitRelativePath;
folderName = relativePath.split("/")[0];
}
const zip = new JSZip();
// 将文件夹及其内容添加到 ZIP 中
Array.from(files).forEach(file => {
zip.file(file.webkitRelativePath, file);
});
// 生成 ZIP 文件
const zipBlob = await zip.generateAsync({ type: "blob" });
// 创建 FormData 对象
/* const formData = new FormData();
formData.append("file", zipBlob, folderName + ".zip");*/
let formData = new FormData()
formData.append('fileName', folderName + ".zip")
// 计算 shardCount
const _shardCount = Math.ceil(zipBlob.size / this.partSize);
const fileObj = {
_shardCount,
size: zipBlob.size,
file: zipBlob // 将 zipBlob 添加到 fileObj 中
};
self.$set(fileObj.file, '_shardCount', _shardCount);
self.$set(fileObj.file, 'uploaded', 0);
self.$set(fileObj.file, 'name', folderName + ".zip");
self.fileList.push(fileObj.file)
if (zipBlob.size < this.partSize) {
let formDataSign = new FormData()
formDataSign.append("file", zipBlob, folderName + ".zip")
self.progressFlag = true;
axios({
url: self.uploadUrl,
method: 'post',
data: formDataSign,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
onUploadProgress: progressEvent => {
// progressEvent.loaded:已上传文件大小
// progressEvent.total:被上传文件的总大小
//进度条
self.progressPercent = ((progressEvent.loaded / progressEvent.total) * 100) | 0;
}
}).then(res => {
setTimeout(() => {
if (res.data.code == 200 && self.progressPercent === 100) {
setTimeout(function () {
self.$message({
message: '上传成功!',
type: 'success',
duration: '2000'
});
self.progressFlag = false;
self.progressPercent = 0
self.handleResult(res,fileObj.file);
}, 500);
} else {
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
}
}, 1000);
}).catch(error => {
console.error(error)
self.progressFlag = false;
self.progressPercent = 0
self.$refs.upload.clearFiles();
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
})
} else {
// 初始化上传,获取 uploadId
axios({
url: process.env.VUE_APP_BASE_API + "/common/initUpload",
method: 'post',
data: formData,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
}).then(function (res) {
if (res.status === 200) {
self.$set(fileObj.file, 'uploadId', res.data.uploadId);
self.$set(fileObj.file, 'chunkId', 0);
self.$set(fileObj.file, 'objectKey', res.data);
/*//从第0块开始上传
fileObj.uploadId = res.data.uploadId;
fileObj.chunkId = 0;
fileObj.objectKey = res.data*/
self.uploadByChunk(fileObj.file);
} else {
self.progress--;
self.$message.error(res.msg);
}
}).catch(error => {
self.progressPercent = 0;
self.progressFlag = false;
console.error(error);
});
}
},
}
};
</script>