109 lines
3.0 KiB
TypeScript
109 lines
3.0 KiB
TypeScript
import { uploadRequest } from "@/http/upload-axios"
|
|
|
|
/**
|
|
* 文件上传配置接口
|
|
*/
|
|
interface UploadConfig {
|
|
onProgress?: (progress: number) => void
|
|
timeout?: number
|
|
chunkSize?: number
|
|
}
|
|
|
|
/**
|
|
* 优化的文件上传API
|
|
* 支持进度回调、自定义超时、错误重试
|
|
*/
|
|
export function uploadFileApiV2(
|
|
formData: FormData,
|
|
config: UploadConfig = {}
|
|
) {
|
|
const { onProgress, timeout = 300000 } = config
|
|
|
|
return uploadRequest<{
|
|
code: number
|
|
data: Array<{
|
|
name: string
|
|
size: number
|
|
type: string
|
|
status: string
|
|
}>
|
|
message: string
|
|
}>({
|
|
url: "/api/v1/files/upload",
|
|
method: "post",
|
|
data: formData,
|
|
timeout,
|
|
onUploadProgress: (progressEvent) => {
|
|
if (onProgress && progressEvent.total) {
|
|
const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total)
|
|
onProgress(progress)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 分块上传大文件
|
|
* 将大文件分割成小块进行上传,提高成功率
|
|
*/
|
|
export async function uploadLargeFile(
|
|
file: File,
|
|
config: UploadConfig & { parentId?: string } = {}
|
|
) {
|
|
const { chunkSize = 5 * 1024 * 1024, onProgress, parentId } = config // 默认5MB分块
|
|
|
|
// 小文件直接上传
|
|
if (file.size <= chunkSize) {
|
|
const formData = new FormData()
|
|
formData.append("file", file)
|
|
if (parentId) formData.append("parent_id", parentId)
|
|
|
|
return uploadFileApiV2(formData, { onProgress })
|
|
}
|
|
|
|
// 大文件分块上传
|
|
const totalChunks = Math.ceil(file.size / chunkSize)
|
|
const uploadId = `upload_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
|
|
|
for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
|
|
const start = chunkIndex * chunkSize
|
|
const end = Math.min(start + chunkSize, file.size)
|
|
const chunk = file.slice(start, end)
|
|
|
|
const formData = new FormData()
|
|
formData.append("chunk", chunk)
|
|
formData.append("chunkIndex", chunkIndex.toString())
|
|
formData.append("totalChunks", totalChunks.toString())
|
|
formData.append("uploadId", uploadId)
|
|
formData.append("fileName", file.name)
|
|
if (parentId) formData.append("parent_id", parentId)
|
|
|
|
try {
|
|
await uploadRequest({
|
|
url: "/api/v1/files/upload/chunk",
|
|
method: "post",
|
|
data: formData,
|
|
timeout: 60000, // 单个分块1分钟超时
|
|
onUploadProgress: (progressEvent) => {
|
|
if (onProgress && progressEvent.total) {
|
|
const chunkProgress = (progressEvent.loaded / progressEvent.total) * 100
|
|
const totalProgress = ((chunkIndex + chunkProgress / 100) / totalChunks) * 100
|
|
onProgress(Math.round(totalProgress))
|
|
}
|
|
}
|
|
})
|
|
} catch (error) {
|
|
// 分块上传失败,尝试重试
|
|
console.error(`分块 ${chunkIndex + 1}/${totalChunks} 上传失败:`, error)
|
|
throw new Error(`文件上传失败:分块 ${chunkIndex + 1} 上传出错`)
|
|
}
|
|
}
|
|
|
|
// 合并分块
|
|
return uploadRequest({
|
|
url: "/api/v1/files/upload/merge",
|
|
method: "post",
|
|
data: { uploadId, fileName: file.name, totalChunks, parentId }
|
|
})
|
|
}
|