使用@aws-sdk上传S3遇问题:大文件报Failed to fetch,小文件正常
问题详情
使用@aws-sdk/client-s3的PutObjectCommand和@aws-sdk/lib-storage向AWS S3存储桶上传文件时,文件大小超过70KB就会触发以下错误,小于该大小的文件可正常上传:
TypeError: Failed to fetch
at FetchHttpHandler.handle (fetch-http-handler.js:56:13)
at PutObjectCommand.js:56:58
at flexibleChecksumsResponseMiddleware.js:17:26
at deserializerMiddleware.js:2:32
at check-content-length-header.js:18:16
at awsAuthMiddleware.js:10:26
at async retryMiddleware.js:24:46
at async flexibleChecksumsMiddleware.js:54:20
at async loggerMiddleware.js:3:26
at async Promise.all (index 0)
upload.ts:31
上传代码如下:
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3"; import { Upload } from "@aws-sdk/lib-storage"; import { FetchHttpHandler } from "@smithy/fetch-http-handler"; const secretAccessKey = import.meta.env.VITE_AWS_SECRET_ACCESS_KEY; const accessKeyId = import.meta.env.VITE_AWS_ACCESS_KEY_ID; const region = import.meta.env.VITE_AWS_DEFAULT_REGION; const bucket = import.meta.env.VITE_BUCKET_NAME; const client = new S3Client({ credentials: { secretAccessKey, accessKeyId }, region, requestHandler: new FetchHttpHandler({ requestTimeout: 5000 }) }); export const onUploadFiles = async (file: any) => { const upload = new Upload({ client, params: { Bucket: bucket, Key: file.name, Body: file.file, ACL: "public-read" }, partSize: 5 * 1024 * 1024 }); try { upload.on("httpUploadProgress", (progress) => { console.log(progress); }); await upload.done(); } catch (error) { console.log(error); } }; export const onUpload = async (file: any, callback: (data: any) => void) => { const input = { Bucket: bucket, Key: file.name, Body: file.file, ACL: "public-read" }; try { const response = await client.send(new PutObjectCommand(input)); callback(response); } catch (error) { console.log(error); } };
解决办法
1. 延长请求超时时间
当前设置的requestTimeout: 5000(5秒)过短,大文件上传需要更长时间完成,超时会导致请求失败。建议将超时时间调整为30秒或更久:
const client = new S3Client({ credentials: { secretAccessKey, accessKeyId }, region, requestHandler: new FetchHttpHandler({ requestTimeout: 30000 // 30秒 }) });
2. 检查并修正S3 CORS配置
存储桶的CORS规则可能限制了大文件上传的请求。确保CORS规则允许PUT方法和必要的请求头,示例配置:
<CORSConfiguration> <CORSRule> <AllowedOrigin>https://your-domain.com</AllowedOrigin> <!-- 替换为实际域名,或用*临时测试 --> <AllowedMethod>PUT</AllowedMethod> <AllowedMethod>POST</AllowedMethod> <AllowedHeader>*</AllowedHeader> <MaxAgeSeconds>3000</MaxAgeSeconds> </CORSRule> </CORSConfiguration>
3. 调整分块上传的partSize
如果网络环境较差,5MB的分块可能容易超时。尝试减小分块大小,比如改为1MB:
const upload = new Upload({ client, params: { Bucket: bucket, Key: file.name, Body: file.file, ACL: "public-read" }, partSize: 1 * 1024 * 1024 // 1MB });
4. 排查浏览器/网络限制
如果是在浏览器环境上传,检查:
- 浏览器开发者工具的Network面板,查看请求是否有具体的状态码(如403、404)或中断原因
- 切换网络环境(比如关闭代理、换用手机热点),排除防火墙/代理拦截
- 确认浏览器没有对大文件上传的限制
5. 验证IAM凭证权限
确保AWS凭证拥有s3:PutObject权限,且资源范围正确:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::your-bucket-name/*" } ] }
内容的提问来源于stack exchange,提问作者André Henrique

