准备
借助antd
的Upload
组件实现批量上传
需要接口支持
接口配置
/** 批量上传图片 */
export function batchUploadImages(data: FormData, config?: AxiosRequestConfig) {
return request<API.BasicResponse>('api地址', {
method: 'post',
data,
config,
})
}
axios配置(基于UMI
)
// 请求拦截器
requestInterceptors: [
(url: any, options: any) => {
// options相当于
// {
// method: 'post',
// data,
// config,
// }
return {
url,
options: {
...options,
// 上传进度条和其他配置
...options.config,
headers: {
Authorization: getToken(),
},
params: {
...options.params,
},
},
}
},
]
Upload组件配置
<Upload
name="files[]" // 由后端决定
disabled={uploadProgress.isUploading}
multiple
showUploadList={false}
fileList={uploadFileList}
customRequest={() => {}} // 阻止默认上传行为
headers={{
Authorization: getToken(),
}}
onChange={handleUploadProgress}
>
<Button icon={<UploadOutlined />}>Upload</Button>
</Upload>
handleUploadProgress
// 图片上传总数
const handleUploadProgress = (info: UploadChangeParam) => {
setUploadFileList(info.fileList)
setUploadProgress((prevState) => {
return {
...prevState,
current: 0,
total: info.fileList.length,
// 将 fileList 分割成多个批次
batches: Math.ceil(info.fileList.length / perBatch),
percent: 0,
}
})
}
handleUploadPicture
const [perBatch, setPerBatch] = useState<number>(20)
// 修改分片大小
const handlePerBatchChange = (value: number | null) => {
if (!value) return
setPerBatch(value)
setUploadProgress((prevState) => {
return {
...prevState,
batches: Math.ceil(prevState.total / value),
}
})
}
// 图片批量上传
const handleUploadPicture = async (fileList: UploadFile[]) => {
setUploadProgress((prevState) => {
return {
...prevState,
isUploading: true,
}
})
// 循环上传每个批次的文件
for (let i = 0; i < uploadProgress.batches; i++) {
const start = i * perBatch
const end = Math.min((i + 1) * perBatch, fileList.length)
const filesToUpload = fileList.slice(start, end)
const formData = new FormData()
filesToUpload.forEach((file) => {
formData.append('files[]', file.originFileObj!)
})
// 使用 await 等待当前批次的文件上传完成
try {
const res = await batchUploadImages(formData, {
onUploadProgress,
timeout: 900000,
})
if (res.code !== 200) {
message
.error({
duration: 10,
content: res.msg || formatMessage({ id: 'intl.upload.error' }),
})
.then()
handleUploadStop()
break
}
// 等待1.5秒,确保服务器端处理完成
await new Promise((resolve) => {
setTimeout(resolve, 1500)
})
} catch (error: any) {
handleUploadStop()
message
.error({
duration: 10,
content:
error.message || formatMessage({ id: 'intl.upload.error' }),
})
.then()
break
}
setUploadProgress((prevState) => {
return {
...prevState,
current: prevState.current + 1,
}
})
if (end === fileList.length) {
setUploadProgress((prevState) => {
return {
...prevState,
isUploading: false,
}
})
setUploadFileList([])
}
}
}
onUploadProgress
这个方法会传给axios的config
中, 显示当前上传进度
// 图片批量上传的进度条
const onUploadProgress = (progressEvent: any) => {
const { loaded, total } = progressEvent
let percent = Math.floor((loaded * 100) / total)
if (percent >= 100) {
setUploadFileList([])
}
setUploadProgress((prevState) => {
return {
...prevState,
percent,
}
})
}
上传速度
可以根据onUploadProgress
的loaded
和total
计算出上传速度