Pre Merge pull request !96 from 秋辞未寒/dev
This commit is contained in:
commit
e596b91fc6
@ -33,3 +33,6 @@ VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
|
|||||||
|
|
||||||
# websocket 开关
|
# websocket 开关
|
||||||
VITE_APP_WEBSOCKET = true
|
VITE_APP_WEBSOCKET = true
|
||||||
|
|
||||||
|
# 文件上传分片大小 默认5M
|
||||||
|
VITE_FILE_UPLOAD_PART_SIZE = 5242880
|
||||||
|
@ -36,3 +36,6 @@ VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
|
|||||||
|
|
||||||
# websocket 开关
|
# websocket 开关
|
||||||
VITE_APP_WEBSOCKET = true
|
VITE_APP_WEBSOCKET = true
|
||||||
|
|
||||||
|
# 文件上传分片大小 默认5M
|
||||||
|
VITE_FILE_UPLOAD_PART_SIZE = 5242880
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
import { OssQuery, OssVO } from './types';
|
import { OssPartUploadVo, OssQuery, OssVO } from './types';
|
||||||
import { AxiosPromise } from 'axios';
|
import { AxiosPromise } from 'axios';
|
||||||
|
|
||||||
// 查询OSS对象存储列表
|
// 查询OSS对象存储列表
|
||||||
@ -26,3 +26,16 @@ export function delOss(ossId: string | number | Array<string | number>) {
|
|||||||
method: 'delete'
|
method: 'delete'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 分片上传
|
||||||
|
export function partUpload(formData: FormData): AxiosPromise<OssPartUploadVo> {
|
||||||
|
return request({
|
||||||
|
url: '/resource/oss/part/upload',
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
// 关闭防重提交
|
||||||
|
repeatSubmit: false
|
||||||
|
},
|
||||||
|
data: formData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -20,3 +20,26 @@ export interface OssQuery extends PageQuery {
|
|||||||
export interface OssForm {
|
export interface OssForm {
|
||||||
file: undefined | string;
|
file: undefined | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface OssPartUploadForm {
|
||||||
|
file: undefined | string;
|
||||||
|
uploadId: undefined | string;
|
||||||
|
fileName: undefined | string;
|
||||||
|
fileSize: undefined | number;
|
||||||
|
partNumber: undefined | number;
|
||||||
|
partSize: undefined | number;
|
||||||
|
totalParts: undefined | number;
|
||||||
|
needMerge: undefined | boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OssPartInfo {
|
||||||
|
partNumber: undefined | number;
|
||||||
|
eTag: undefined | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OssPartUploadVo {
|
||||||
|
uploadId: undefined | string;
|
||||||
|
url: undefined | string;
|
||||||
|
partInfoList: undefined | Array<OssPartInfo>;
|
||||||
|
mergeCompleted: undefined | boolean;
|
||||||
|
}
|
||||||
|
150
src/components/FilePartUpload/index.vue
Normal file
150
src/components/FilePartUpload/index.vue
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
<template>
|
||||||
|
<div class="upload-file" style="width: 90%">
|
||||||
|
<el-upload
|
||||||
|
class="upload-demo"
|
||||||
|
action="#"
|
||||||
|
drag
|
||||||
|
multiple
|
||||||
|
:auto-upload="false"
|
||||||
|
:file-list="fileList"
|
||||||
|
:show-file-list="true"
|
||||||
|
:on-change="handleChange"
|
||||||
|
:on-remove="handleRemove"
|
||||||
|
>
|
||||||
|
<el-icon class="el-icon--upload">
|
||||||
|
<upload-filled />
|
||||||
|
</el-icon>
|
||||||
|
<div class="el-upload__text">
|
||||||
|
将文件拖到此处,或<em>点击上传</em>
|
||||||
|
</div>
|
||||||
|
<!-- <template #tip>-->
|
||||||
|
<!-- <div class="el-upload__tip">-->
|
||||||
|
<!-- 请上传大小不超过 <b style="color: #f56c6c"> 500MB</b> 的文件-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </template>-->
|
||||||
|
</el-upload>
|
||||||
|
</div>
|
||||||
|
<div class="float-left">
|
||||||
|
<el-button type="success" @click="startUpload">开始上传</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { partUpload } from '@/api/system/oss';
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
|
// 分片大小
|
||||||
|
const partSize = Number(import.meta.env.VITE_FILE_UPLOAD_PART_SIZE);
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
file: null, // 文件
|
||||||
|
uploadId: null, // uploadId 上传ID 上传第一片不需要传递,后续需要,从第一次上传的响应中取得
|
||||||
|
fileName: null, // 文件名(带后缀)
|
||||||
|
fileSize: 0, // 文件(总)大小
|
||||||
|
partNumber: 0, // 当前分片序号
|
||||||
|
totalParts: 0, // 总片数
|
||||||
|
fileParts: [] // 文件分片数组
|
||||||
|
});
|
||||||
|
|
||||||
|
const fileList = ref([]);
|
||||||
|
|
||||||
|
// 开始上传分片
|
||||||
|
const startUpload = () => {
|
||||||
|
proxy?.$modal.loading('正在上传文件,请稍候...');
|
||||||
|
uploadNextPart();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 实际分片上传函数
|
||||||
|
const uploadNextPart = () => {
|
||||||
|
if (state.partNumber < state.totalParts) {
|
||||||
|
const filePart = state.fileParts[state.partNumber];
|
||||||
|
const partNumber = state.partNumber + 1;
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', filePart);
|
||||||
|
// 上传第一片时,uploadId是不存在的
|
||||||
|
if (state.uploadId) {
|
||||||
|
formData.append('uploadId', state.uploadId);
|
||||||
|
}
|
||||||
|
formData.append('fileName', state.fileName);
|
||||||
|
formData.append('fileSize', state.fileSize);
|
||||||
|
formData.append('partNumber', partNumber);
|
||||||
|
formData.append('partSize', partSize);
|
||||||
|
formData.append('totalParts', state.totalParts);
|
||||||
|
// 是否需要合并,如果已经是最后一片,则自动合并
|
||||||
|
formData.append('needMerge', partNumber === state.totalParts);
|
||||||
|
|
||||||
|
partUpload(formData)
|
||||||
|
.then((res) => {
|
||||||
|
handleUploadSuccess(res);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
handleUploadError(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 上传成功回调
|
||||||
|
const handleUploadSuccess = (res: any) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
if (res.data.mergeCompleted) {
|
||||||
|
proxy?.$modal.msgSuccess('文件上传完成');
|
||||||
|
uploadedSuccessfully();
|
||||||
|
} else {
|
||||||
|
// 继续上传下一片,如果需要做断点或者暂停上传,可以在这里做介入
|
||||||
|
state.partNumber++;
|
||||||
|
if (res.data.uploadId && !state.uploadId) {
|
||||||
|
state.uploadId = res.data.uploadId;
|
||||||
|
}
|
||||||
|
uploadNextPart();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
proxy?.$modal.closeLoading();
|
||||||
|
proxy?.$modal.msgError(res.msg);
|
||||||
|
uploadedSuccessfully();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 上传结束处理
|
||||||
|
const uploadedSuccessfully = () => {
|
||||||
|
proxy?.$modal.closeLoading();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 上传失败
|
||||||
|
const handleUploadError = (error: any) => {
|
||||||
|
proxy?.$modal.msgError('上传文件失败');
|
||||||
|
proxy?.$modal.closeLoading();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 文件发生更改时
|
||||||
|
const handleChange = (uploadFile, uploadFiles) => {
|
||||||
|
stateReset();
|
||||||
|
state.file = uploadFile;
|
||||||
|
state.fileName = state.file.name;
|
||||||
|
state.fileSize = state.file.size;
|
||||||
|
const totalParts = Math.ceil(state.file.size / partSize);
|
||||||
|
state.totalParts = totalParts;
|
||||||
|
// 计算分片
|
||||||
|
for (let i = 0; i < totalParts; i++) {
|
||||||
|
const start = i * partSize;
|
||||||
|
const end = start + partSize >= state.file.size ? state.file.size : start + partSize;
|
||||||
|
const filePart = state.file.raw?.slice(start, end);
|
||||||
|
state.fileParts.push(filePart);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 文件移除时
|
||||||
|
const handleRemove = (uploadFile, uploadFiles) => {
|
||||||
|
stateReset();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置状态
|
||||||
|
const stateReset = () => {
|
||||||
|
state.file = null;
|
||||||
|
state.fileParts = [];
|
||||||
|
state.fileName = null;
|
||||||
|
state.fileSize = 0;
|
||||||
|
state.partNumber = 0;
|
||||||
|
state.totalParts = 0;
|
||||||
|
};
|
||||||
|
</script>
|
@ -45,6 +45,9 @@
|
|||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button v-hasPermi="['system:oss:upload']" type="primary" plain icon="Upload" @click="handleImage">上传图片</el-button>
|
<el-button v-hasPermi="['system:oss:upload']" type="primary" plain icon="Upload" @click="handleImage">上传图片</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button v-hasPermi="['system:oss:upload']" type="primary" plain icon="Upload" @click="handlePartFile">分片上传</el-button>
|
||||||
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button v-hasPermi="['system:oss:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
|
<el-button v-hasPermi="['system:oss:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
|
||||||
删除
|
删除
|
||||||
@ -118,6 +121,7 @@
|
|||||||
<el-form-item label="文件名">
|
<el-form-item label="文件名">
|
||||||
<fileUpload v-if="type === 0" v-model="form.file" />
|
<fileUpload v-if="type === 0" v-model="form.file" />
|
||||||
<imageUpload v-if="type === 1" v-model="form.file" />
|
<imageUpload v-if="type === 1" v-model="form.file" />
|
||||||
|
<filePartUpload v-if="type === 2" v-model="form.file" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@ -295,6 +299,13 @@ const handleImage = () => {
|
|||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = '上传图片';
|
dialog.title = '上传图片';
|
||||||
};
|
};
|
||||||
|
/** 分片上传按钮操作 */
|
||||||
|
const handlePartFile = () => {
|
||||||
|
reset();
|
||||||
|
type.value = 2;
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = '分片上传';
|
||||||
|
};
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user