1、背景
antd 版本 ^4.20.0
2、分片实现
const [fileList, setFileList] = useState([]);
// 上传前文件格式校验 ---压缩包
const beforeUpload = (file) => {
let reg = /([^\\/]+)\.([^\\/]+)/i;
reg.test(file.name);
const isZip = RegExp.$2 === "zip" || RegExp.$2 === "rar" || RegExp.$2 === "7z"
if (!isZip) {
message.warn('请上传正确的文件类型,支持zip,rar,7z格式的压缩包!');
}
return isZip;
}
// 分片同步上传
const handleCustomRequest = async({ file, onSuccess, onError, onProgress }) => {
const sliceSize = 10 * 1024 * 1024; // 切片大小,这里假设每个切片1MB
const totalSlices = Math.ceil(file.size / sliceSize); // 获取切片数量
let chunk = 0;
let postPromises = []; // 存储每个 POST 请求的 Promise
let totalUploaded = 0; // 总已上传数据量
const nameList = file.name.split('.');
while (chunk < totalSlices) {
const start = chunk * sliceSize;
const end = Math.min(start + sliceSize, file.size);
const slice = file.slice(start, end); // 上传的分片,通过开始结束截取
const timestamp = Date.now();
const formData = new FormData();
// 上传接口入参
formData.append('file', slice);
formData.append('chunk', chunk + 1);
formData.append('fileName', nameList[0]);
formData.append('currentFolderPath', file.uid);
const postPromise = axios.post(url, formData, {
// 进度条处理
onUploadProgress: (progressEvent) => {
if(progressEvent.loaded == progressEvent.total){
totalUploaded += progressEvent.loaded;
const overallProgress = Math.round((totalUploaded * 100) / file.size);
onProgress({ percent: overallProgress });
} else {
const loadedSize = totalUploaded + progressEvent.loaded;
const overallProgress = Math.round((loadedSize * 100) / file.size);
onProgress({ percent: overallProgress });
}
},
})
postPromises.push(postPromise);
chunk ++;
}
try {
const arrList = await Promise.all(postPromises);
const successList = arrList.filter((v) => (v.data && v.data.code == 0))
// 所有分片上传成功 才算成功
if(successList.length == arrList.length){
onSuccess({ code: 0, data: successList })
} else {
onError()
}
} catch (error) {
onError()
}
}
const onUpdateChange = (info) => {
const { file } = info;
const { status, response } = info.file;
if (utils.helper.isEmptyObj(info.fileList)){
return ;
}
if (fileList && fileList.length > 0 && file.uid != fileList[0].uid) {
// 若上传分片未结束,改变了上传的文件,需要将上次上传的部分分片删除处理
// batchImportApi.delPartFile({ currentFolderPath: fileList[0].uid })
}
if (status) {
const newFileList = [...info.fileList];
setFileList(newFileList);
}
if (status === 'done') {
if (response && response.code === 0) {
message.success(`${info.file.name} 上传成功!`)
}
} else if (status === 'error') {
message.error(`${info.file.name} 上传失败.`);
setFileList([]);
}
}
const onRemoveList = () => {
// 删除 已成功上传的文件
// batchImportApi.delPartFile({ currentFolderPath: fileList[0].uid }).then((res) => {
// if(res.code == 0){
// setFileList([]);
// }
// })
}
const fileProps = {
name: 'file',
beforeUpload: beforeUpload,
onChange: onUpdateChange,
multiple: false,
headers: { mappingPath: window.location.pathname.replace(/\//g, '') },
customRequest: handleCustomRequest,
onRemove: onRemoveList,
}
<Dragger {...fileProps} maxCount={1} fileList={fileList}>
<div className={styles.uploadFile}>
<CloudUploadOutlined style={{ fontSize: 24 }}/>
<div style={{ marginTop: 8 }}>请上传包含内容文件的压缩文件</div>
</div>
</Dragger>