From 8044855bbd1b46a569173c0458bec0a2abab852b Mon Sep 17 00:00:00 2001 From: shenhan000 Date: Mon, 24 Mar 2025 13:23:37 +0800 Subject: [PATCH] uodate --- app/components/fileUpload/index.vue | 149 +++++++++++++++----- app/components/publishModel/EditVersion.vue | 4 +- app/components/publishModel/UploadImg.vue | 17 ++- app/pages/personal-center/index.vue | 5 +- app/pages/publish-model/index.vue | 1 + nuxt.config.ts | 4 +- 6 files changed, 136 insertions(+), 44 deletions(-) diff --git a/app/components/fileUpload/index.vue b/app/components/fileUpload/index.vue index 2e67f40..3568c50 100644 --- a/app/components/fileUpload/index.vue +++ b/app/components/fileUpload/index.vue @@ -30,7 +30,12 @@ processing /> -
请上传文件
+ + @@ -77,7 +82,7 @@ const fileName = ref(""); const fileSize = ref(0); const progress = ref(0); const objectKey = ref(""); -const chunkSize = ref(3 * 1024 * 1024); +const chunkSize = ref(5 * 1024 * 1024); const totalChunks = ref(0); const currentChunk = ref(1); const uploadId = ref(""); @@ -89,6 +94,13 @@ const requiredValid = ref(false); const hashCode = ref(""); const message = useMessage(); const currentFileSize = ref(0) + +// 添加新的状态来跟踪上传状态 +const uploadStatus = ref<'idle' | 'uploading' | 'paused' | 'completed'>('idle'); +const uploadedChunks = ref>(new Set()); +const retryCount = ref(0); +const maxRetries = 5; // 最大重试次数 + // 触发文件选择 const triggerFileSelect = () => { fileInputRef.value?.click(); @@ -162,6 +174,9 @@ const initParam = () => { uploadId.value = ""; partArr.value = []; requiredValid.value = false; + uploadStatus.value = 'idle'; + uploadedChunks.value.clear(); + retryCount.value = 0; }; function getOssDefaultPath(name:any) { @@ -200,6 +215,18 @@ const selectFile = async (event: Event) => { } try { + // 如果存在未完成的上传,询问是否继续 + if (uploadStatus.value === 'paused' && file.value) { + const shouldResume = window.confirm('检测到未完成的上传,是否继续上传?'); + if (shouldResume) { + await resumeUpload(); + return; + } else { + // 用户选择重新上传,清除之前的上传状态 + initParam(); + } + } + // 继续上传流程 progress.value = 0; fileName.value = file.value.name; @@ -244,8 +271,15 @@ const selectFile = async (event: Event) => { // 检查文件是否已存在 // 上传文件前先校验是否存在 存在为0 不存在为1 try { - const res = await request.get( - `/file/selectFile?type=${props.type}&name=${fileName.value}` + // const res = await request.get( + // `/file/selectFile?type=${props.type}&name=${fileName.value}` + // ); + const res = await request.post( + `/file/selectFile`, + { + type:props.type, + name:fileName.value + } ); if (res.data !== 1) { message.warning("文件名已存在"); @@ -314,35 +348,76 @@ const selectFile = async (event: Event) => { const uploadFile = async () => { if (!file.value) return; - const index = currentChunk.value - 1; - const start = index * chunkSize.value; - const end = Math.min((index + 1) * chunkSize.value, file.value.size); - - const formData = new FormData(); - formData.append("file", file.value.slice(start, end)); - formData.append("chunk", String(currentChunk.value)); - formData.append("objectKey", objectKey.value); - formData.append("uploadId", uploadId.value); - - try { - const res = await request.post("/file/chunk", formData, { - headers: { "Content-Type": "multipart/form-data" }, - }); - - partArr.value.push(res.data); - currentChunk.value++; - progress.value = Math.floor((currentChunk.value / totalChunks.value) * 100); - - if (currentChunk.value <= totalChunks.value) { - uploadFile(); - } else { - progress.value = 99; - complete(); + while (currentChunk.value <= totalChunks.value) { + // 如果这个分片已经上传成功,跳过 + if (uploadedChunks.value.has(currentChunk.value)) { + currentChunk.value++; + continue; } - } catch (error) { - initParam(); - console.error("切片上传失败:", error); - message.warning("文件上传异常或上传已取消"); + + const index = currentChunk.value - 1; + const start = index * chunkSize.value; + const end = Math.min((index + 1) * chunkSize.value, file.value.size); + + const formData = new FormData(); + formData.append("file", file.value.slice(start, end)); + formData.append("chunk", String(currentChunk.value)); + formData.append("objectKey", objectKey.value); + formData.append("uploadId", uploadId.value); + + try { + uploadStatus.value = 'uploading'; + const res = await request.post("/file/chunk", formData, { + headers: { "Content-Type": "multipart/form-data" }, + // 添加上传进度监听 + onUploadProgress: (progressEvent) => { + const percentCompleted = Math.round( + ((currentChunk.value - 1) / totalChunks.value) * 100 + + (progressEvent.loaded / progressEvent.total!) * (100 / totalChunks.value) + ); + progress.value = percentCompleted; + } + }); + + // 记录成功上传的分片 + uploadedChunks.value.add(currentChunk.value); + partArr.value.push(res.data); + currentChunk.value++; + retryCount.value = 0; // 重置重试计数 + + progress.value = Math.floor((currentChunk.value / totalChunks.value) * 100); + } catch (error) { + console.error("切片上传失败:", error); + + // 重试逻辑 + if (retryCount.value < maxRetries) { + retryCount.value++; + message.warning(`第 ${currentChunk.value} 个分片上传失败,正在进行第 ${retryCount.value} 次重试...`); + await new Promise(resolve => setTimeout(resolve, 1000)); // 等待1秒后重试 + continue; // 重试当前分片 + } + + // 超过最大重试次数 + uploadStatus.value = 'paused'; + message.error(`上传失败,已暂停。您可以稍后继续上传。`); + return; + } + } + + // 所有分片上传完成 + if (currentChunk.value > totalChunks.value) { + progress.value = 99; + uploadStatus.value = 'completed'; + await complete(); + } +}; + +// 添加继续上传方法 +const resumeUpload = async () => { + if (uploadStatus.value === 'paused' && file.value) { + retryCount.value = 0; // 重置重试计数 + message.info('正在继续上传...'); + await uploadFile(); } }; @@ -389,19 +464,21 @@ const emit = defineEmits<{ // 取消上传 const cancelUploadInfo = async () => { - if (progress.value !== 100) { + if (uploadStatus.value !== 'completed') { try { await request.post("/file/cancelUpload", { objectKey: objectKey.value, uploadId: uploadId.value, }); + uploadStatus.value = 'idle'; + uploadedChunks.value.clear(); + progress.value = 0; + showFileName.value = false; + initParam(); } catch (error) { message.error("取消上传失败"); } } - progress.value = 0; - showFileName.value = false; - initParam(); }; // 校验是否已上传 diff --git a/app/components/publishModel/EditVersion.vue b/app/components/publishModel/EditVersion.vue index 4d3b607..4d02df3 100644 --- a/app/components/publishModel/EditVersion.vue +++ b/app/components/publishModel/EditVersion.vue @@ -367,7 +367,7 @@ function handledeleteFile(item:any){ v-model:checked="item.isOnlineUse" :checked-value="1" :unchecked-value="0" - disabled="true" + :disabled="true" label="允许在魔创未来在线使用" /> @@ -383,7 +383,7 @@ function handledeleteFile(item:any){ diff --git a/app/components/publishModel/UploadImg.vue b/app/components/publishModel/UploadImg.vue index 30411bc..4265a13 100644 --- a/app/components/publishModel/UploadImg.vue +++ b/app/components/publishModel/UploadImg.vue @@ -1,6 +1,6 @@