前言
多文件上传本质是循环存储的过程,只是在实现方式有所区别,
实现方式:
- 前端批量上传:前端轮询调用后端单文件上传接口
- 后端批量存储:一次性接收前端多文件,循环存储
组件 vs 定制化
antd中的upload组件功能强大,支持文件夹、拖拽、自动上传、ui美观,文档完善,通过简单配置即可开发完功能,以功能为主的开发,建议使用组件完成
如果定制化功能,业务交互复杂,建议手写上传功能,其本质将file类型的数据,以fomdata的格式发送给后端。
如实现多文件上传,建议搭配promise使用,promise.all() 可等待多个异步操性、结合此特性实现批量上传的效果。
示例代码
antd-upload自动上传
// 初始化 上传组件的列表数据 const [fileList, setFileList] = useState<UploadFile[]>([]); // uoload 组件配置项 const props = { beforeUpload: (file: File) => { if (file.size > maxFileSize) { message.warning('文件最多上传1m') return Upload.LIST_IGNORE } // console.log(file, 'file') // const isPNG = file.type === 'image/png'; // if (!isPNG) { // message.error(`${file.name} is not a png file`); // } // return isPNG || Upload.LIST_IGNORE; // return true }, action: 'http:///localhost:9981/upload_oss',/// 接口地址 oss or 本地 onChange: handleChange, multiple: true, }; // upload 组件change事件 const handleChange: UploadProps['onChange'] = (info) => { console.log('oonchang', info) let newFileList = [...info.fileList]; newFileList = newFileList.map((file) => { if (file.response) { // Component will show file.url as link file.url = file.response.url; } return file; }); setFileList(newFileList); }; // 支持拖拽的上传组件 <Dragger height={70} {...props} fileList={fileList} listType="picture"> <p>支持拖拽上传</p> </Dragger>
antd-upload +promise.all 批量上传
// 封装上传函数 const uploadFiles = (file: any) => { console.log('file', file) const formData = new FormData() formData.append('file', file.originFileObj) return new Promise((resolve, rejects) => { request.post('/upload_oss', formData).then((response) => { resolve(response.data.imgUrl) message.success(`${file.name} 以上传成功`) console.log('startFileList', startFileList) }).catch((err) => { rejects(err) }) }) } // 提交上传 const multipleUpload = async () => { const uploadPromiess = startFileList.map((file) => uploadFiles(file)) let imgs = await Promise.all(uploadPromiess) console.log('全部上传成功', imgs) } // 上传组件chang事件 const handleChange1: UploadProps['onChange'] = (info) => { let newFileList = [...info.fileList]; console.log('触发了') newFileList = newFileList.map((file) => { // Component will show file.url as link try { // file 生成临时的url file.url = URL.createObjectURL(file.originFileObj as RcFile); } catch (error) { } return file; }); console.log('oonchang', newFileList) // 更新 setStrartFileList(newFileList); }; <Upload { ...{ multiple: true, maxCount: 10, fileList: startFileList, onRemove: (file) => { const index = startFileList.indexOf(file); const newFileList = startFileList.slice(); newFileList.splice(index, 1); // setStrartFileList([]); }, beforeUpload: (file: any) => { console.log('filelist', startFileList); // return Upload.LIST_IGNORE - 文件不进行回显 // return false 关闭上传请求 return false }, listType: 'picture', onChange: handleChange1 } }> </Upload> <Button > 选择文件</Button><br></br> <div> <p> 以选中{startFileList.length}个文件,已上传</p></div> <Button onClick={multipleUpload}>提交</Button>