如何在AWS SDK JS v3中实现S3多图片批量上传?
多文件批量上传改造实现
你现有单图上传逻辑可以直接复用,只需要做三处调整即可支持多文件批量上传,不需要额外引入依赖。
1. 调整状态与文件选择控件
原来的单文件状态只能存一个File对象,先替换为数组状态存储多文件,同时给文件选择框加multiple属性支持多选:
// 替换原单文件状态 const [fileList, setFileList] = useState<File[]>([]); // 文件选择控件新增multiple属性,可加accept限制仅选图片 <input type="file" id="file" multiple accept="image/*" onChange={fileChange} />
对应的文件选择回调也要同步修改,把选中的文件列表转成数组存入状态:
const fileChange = (e: React.ChangeEvent<HTMLInputElement>) => { const selectedFiles = Array.from(e.target.files || []); setFileList(selectedFiles); };
2. 改造上传逻辑
你之前写的mediaData FormData拼装是后端中转上传的写法,直连S3的场景不需要这部分,直接遍历选中的文件,为每个文件生成独立的S3上传任务即可。
注意S3客户端和凭证只需要初始化一次,不要每个文件重复创建:
const handleUpload = async () => { if (!fileList.length) { console.warn('请先选择需要上传的文件'); return; } // 统一初始化S3客户端与凭证 const creds = { accessKeyId: process.env.REACT_APP_HOST_AWS_ACCESS_KEY_ID || '', secretAccessKey: process.env.REACT_APP_HOST_AWS_SECRET_ACCESS_KEY || '', }; const s3Client = new S3Client({ region: process.env.REACT_APP_HOST_AWS_DEFAULT_REGION || '', credentials: creds, }); // 总进度统计 const totalFileSize = fileList.reduce((sum, file) => sum + file.size, 0); const progressMap = new Map<string, number>(); // 为每个文件生成上传任务 const uploadTasks = fileList.map((file) => { // 生成唯一存储路径,加时间戳避免同名文件覆盖 const storageKey = `events/${eventDetails.id}/${Date.now()}_${file.name}`; const uploadParams = { Bucket: process.env.REACT_APP_HOST_AWS_BUCKET, Key: storageKey, Body: file, // 动态读取文件类型,不要写死image/jpg,否则png/webp等格式会异常 ContentType: file.type || 'image/jpeg', }; const uploader = new Upload({ client: s3Client, leavePartsOnError: false, params: uploadParams, }); // 单文件进度汇总为总进度 uploader.on('httpUploadProgress', (progress) => { progressMap.set(storageKey, progress.loaded || 0); const totalLoaded = Array.from(progressMap.values()).reduce((sum, cur) => sum + cur, 0); console.log(`上传进度:${Math.round((totalLoaded / totalFileSize) * 100)}%`); }); // 返回上传Promise,完成后返回文件信息 return uploader.done().then((res) => ({ originName: file.name, storageKey, fileUrl: res.Location, })); }); try { // 并行执行所有上传任务,等待全部完成 const allUploadedFiles = await Promise.all(uploadTasks); console.log('全部文件上传完成', allUploadedFiles); // 后续可将allUploadedFiles提交到业务后端存储关联关系 } catch (err) { console.error('上传失败', err); } };
注意事项
- 如果你后续需要改成后端中转上传(不直连S3),直接把之前拼好的
mediaData通过POST请求发给后端接口即可,不需要前端初始化S3客户端 - 如果单次要传的大文件数量较多,可以加并发控制(比如同时最多传3个文件),避免一次性发起太多请求导致浏览器卡顿
- 存储路径建议加随机串/时间戳前缀,避免不同用户上传同名文件导致资源覆盖
- 不要硬编码
ContentType为image/jpg,优先读取文件自带的MIME类型,否则会导致非jpg格式的图片上传后无法正常预览
内容的提问来源于stack exchange,提问作者razer
相关产品推荐
相关产品推荐

