fileUpload.vue 子组件
<template>
<!-- miniion 版本 -->
<!-- 多文件分片上传Minio -->
<div class="multipleFilePartUploadMinio">
<el-upload
ref="upload"
name="files"
action="#"
:on-change="selectMultiplePartFileMinio"
:on-remove="removeMultiplePartFileMinio"
:file-list="fileList"
:auto-upload="false"
:show-file-list="false"
>
<el-button slot="trigger" size="small" type="primary">
{{ upBtnVal }}</el-button
>
<el-button
v-if="isShowButton"
style="margin-left: 10px"
size="small"
type="success"
@click="multipleFilePartUploadMinio"
>点击上传
</el-button>
<el-link
v-else
style="margin-left: 10px"
size="small"
type="success"
@click="multipleFilePartUploadMinio"
>点击上传</el-link
>
<div slot="tip" class="el-upload__tip"></div>
</el-upload>
<el-progress
:text-inside="true"
:stroke-width="15"
:percentage="filePercentage"
></el-progress>
<!-- 文件列表 -->
<transition-group
:style="{ display: fileList.length === 0 ? 'none' : 'inline-block' }"
class="upload-file-list el-upload-list el-upload-list--text"
name="el-fade-in-linear"
tag="ul"
>
<!-- :key="file.uid" -->
<li
class="el-upload-list__item ele-upload-list__item-content sNone"
:style="{ marginBottom: fileList.length > 1 ? '10px !important' : 0 }"
v-for="(file, index) in fileList"
:key="index"
>
<!-- @click="downLoad(file)" -->
<span class="el-icon-paperclip">
<span class="baseColor">
{{ file.name }}
</span>
({{ formatBytes(file.size) }})
</span>
<span
class="ele-upload-list__item-content-action"
style="margin-left: 20px"
@click="handleDelete(index)"
>
<!-- v-if="baseFileList.length" -->
<i class="el-icon-close"></i>
</span>
</li>
</transition-group>
</div>
</template>
<script>
import { initFile, mergeFile, uploadFile } from "@/api/common";
import Axios from "axios";
export default {
props: {
upBtnVal: {
type: String,
default: "选取文件",
},
isShowButton: {
type: Boolean,
default: true,
},
// 是否展示
fileShow: {
type: Boolean,
default: false,
},
baseFileList: {
type: Array,
default: () => [],
},
},
name: "JsPage",
data() {
return {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
filePercentage: 0,
fileList: [],
isUploadSuccess: true,
timerId: null,
callCount: 0,
};
},
mounted() {},
watch: {
baseFileList: {
handler(newVal) {
this.fileList = newVal;
},
deep: true,
immediate: true,
},
},
/* 组件销毁时清除定时器 */
destroyed() {
this.timerId = null;
},
methods: {
// 删除文件
handleDelete(index) {
this.fileList.splice(index, 1);
this.$emit("input", this.fileList);
},
// 下面多文件分片上传Minio的一些方法
selectMultiplePartFileMinio(file, fileList) {
this.filePercentage = 0;
this.fileList.push(file);
},
/* 移除文件 */
removeMultiplePartFileMinio(file, fileList) {
this.fileList = this.fileList.filter((item) => item.uid != file.uid);
this.filePercentage = 0;
},
// 上传
async multipleFilePartUploadMinio() {
if (!this.fileList.length) {
this.$modal.msgWarning("请选择需要上传的文件");
return;
}
this.filePercentage = 0;
let fileUploadCount = 0;
let partSize = 20; //MB
let fileList = this.fileList.filter((item) => item.raw);
for (let i = 0; i < fileList.length; i++) {
let partNum = Math.ceil(this.fileList[i].size / 1024 / 1024 / partSize);
if (partNum > 1) {
let partFileIndex = {
filename: fileList[i].name,
partCount: partNum,
partIndex: "",
};
const res = await initFile(partFileIndex);
if (res.uploadId) {
let urlList = res.uploadUrls;
let urlUploadId = res.uploadId;
for (let j = 0; j < partNum; j++) {
partFileIndex.partIndex = j;
let file=fileList[i].raw.slice(
j * 1024 * 1024 * partSize,
(j + 1) * 1024 * 1024 * partSize
)
Axios.put(urlList[j], file, this.headers).then(
async (response) => {
fileUploadCount++;
this.filePercentage = Math.round(
(fileUploadCount / partNum) * 100
);
if (fileUploadCount == partNum) {
let mergeData = {
objectName:
this.dateColumnFormatNotDash("", "", new Date()) +
"/" +
this.fileList[i].name, //这个是"日期/文件名"
uploadId: urlUploadId, //这个是调第一个接口生成的id
};
const resMerge = await mergeFile(mergeData);
if (resMerge.success) {
// 合并文件成功后,将url返回给fileList
this.$modal.msgSuccess("上传成功");
// 将url结果返回给filelist
this.fileList[i].fileUrl = resMerge.fileUrl;
this.$emit("fileChildList", [...this.fileList]);
this.isUploadSuccess = false;
this.$emit("isUploadSuccess", this.isUploadSuccess);
}
}
}
);
}
}
} else {
// 调取之前的上传
let partFileIndex = {
fileName: fileList[i].name,
fileUid: fileList[i].uid,
};
let fileParam = new FormData();
fileParam.append("file", fileList[i].raw);
fileParam.append("partFileIndex", JSON.stringify(partFileIndex));
const resFile = await uploadFile(fileParam);
if (resFile.code == 200 || resFile.code == 2000) {
this.filePercentage = 100;
// 合并文件成功后,将url返回给fileList
this.$modal.msgSuccess("上传成功");
// 将url结果返回给filelist
this.fileList[i].fileUrl = resFile.msg;
this.$emit("fileChildList", [...this.fileList]);
this.isUploadSuccess = false;
this.$emit("isUploadSuccess", this.isUploadSuccess);
} else {
this.$modal.msgError("上传失败,请重试");
}
this.timer = setInterval(() => {
this.filePercentage++;
if (this.filePercentage > 90) {
clearInterval(this.timer);
this.timer = null;
}
}, 900);
}
}
},
},
};
</script>
<style lang="scss" scoped>
::v-deep .el-progress-bar__innerText {
margin-top: -7px;
}
.upload-file-list {
display: inline-block;
}
.upload-file-list .el-upload-list__item {
line-height: 2;
margin-bottom: 10px;
position: relative;
}
.ele-upload-list__item-content-action .el-link {
margin-right: 10px;
}
.sNone:hover {
background-color: inherit !important;
}
.sNone {
line-height: 0 !important;
margin-bottom: 0 !important;
margin-top: 0 !important;
}
.el-icon-close {
top: 1px;
}
.pointer {
cursor: pointer;
}
</style>
父组件
<file-upload
@fileChildList="getFileList"
@isUploadSuccess="isUploadSuccess"
:baseFileList="fileList"
:isShowButton="true"
/>
api接口
//初始化
export function initFile(data) {
return request({
url: "/fileApi/multipart/init",
method: "post",
data,
});
}
// 文件合并
export function mergeFile(data) {
return request({
url: "/fileApi/multipart/complete",
method: "put",
data,
});
}
// 上传文件
export function uploadFile(data) {
return request({
url: "/fileApi/uploadFile",
method: "post",
data,
headers: {
"Content-Type": "multipart/form-data;charset=utf-8",
},
});
}
上传成功拿到文件信息进行业务提交