大文件上传思路,以及实现
4 分钟
思路:
前端拿到文件后,对文件进行切片操作,然后每个分片发送请求给到后端,所有切片都请求成功后,发送一个合并请求,后端进行文件合并
核心代码如下:
const handleCustomRequest = async ({ file }: { file: File }) => {
if(!file) return
// 切片
const fileChunkList = createFileChunk(file)
filesListInfo.current = fileChunkList.map(() => 0)
try {
if(fileChunkList.length > 0){
const formDataFirst = new FormData()
formDataFirst.append("file", fileChunkList[0]?.file)
setLoading(true)
const res = await uploadFile(formDataFirst, (e: ProgressEvent) => onUploadProgress(e, 0))
if(fileChunkList.length > 1){
for (let i = 1; i < fileChunkList.length; i++) {
const formData = new FormData()
formData.append("file", fileChunkList[i].file)
formData.append("uploadId", res.data.uploadId)
await uploadFile(formData, (e: ProgressEvent) => onUploadProgress(e, i))
}
}
// 合并
await mergeUploadFile({ uploadId: res?.data?.uploadId })
message.success(f('上传成功'))
setLoading(false)
refreshInfo()
}
} catch (error) {
message.error(error?.response?.data?.msg || f('上传失败'))
setLoading(false)
}
}
切片
const createFileChunk = (file: File, size = SIZE) => {
const fileChunkList: {file: Blob}[] = []
let cur = 0
while (cur < file.size) {
fileChunkList.push({ file: file.slice(cur, cur + size) })
cur += size
}
return fileChunkList
}
滚动条展示
前端已知切片总数 Process = 所有切片进度累加 / 总进度
const onUploadProgress = (progressEvent: ProgressEvent, index: Number) => {
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
filesListInfo.current[index] = percentCompleted
const newProcess = (filesListInfo.current.reduce((pre, cur)=>{
return pre + cur
}, 0) / (filesListInfo.current.length))
setProcess(newProcess)
}
优化 1、暂停上传 2、断点续传 3、文件秒上传(已经上传过的文件)
此文自动发布于:github issues