使用getSignedUrlPromise生成预签名URL上传AWS S3返回400错误如何解决
问题根因&修复方案
- 服务端生成预签名URL时未包含
ContentType参数,签名校验不匹配
你当前的generatePreSignedPutUrl函数接收了fileType参数但没有用到,前端上传时指定了Content-Type头,AWS会校验签名时的参数和实际请求参数是否一致,参数不一致直接返回400。
修改服务端代码如下:
- 服务端生成预签名URL时未包含
export const generatePreSignedPutUrl = async (fileName, fileType) => { const params = ({ Bucket: bucketName, Key: fileName, Expires: 60, // 新增这行,把文件类型加入签名参数 ContentType: fileType }) const url = await s3.getSignedUrlPromise('putObject', params); return url; }
- 前端上传时
Content-Type配置错误
你当前设置的multipart/form-data是表单文件上传的格式,直接上传文件二进制流不需要用这个类型,要和服务端签名时的fileType保持一致:
修改前端上传代码如下:
- 前端上传时
const response = await fetch(url, { method: "PUT", headers: { // 替换成文件本身的MIME类型,和服务端签名的ContentType一致 "Content-Type": frontPhoto.type }, body: frontPhoto }); // 可新增这行打印具体错误信息,方便后续排查问题 console.log(await response.text())
- 检查S3存储桶CORS配置
你收到的响应类型是cors,需要确认S3存储桶的跨域规则允许你的前端域名发起PUT请求,示例CORS规则如下(可在S3控制台存储桶的「权限」-「跨源资源共享(CORS)」中配置):
- 检查S3存储桶CORS配置
[ { "AllowedHeaders": ["*"], "AllowedMethods": ["PUT", "GET"], "AllowedOrigins": ["替换为你的前端域名,例如https://your-domain.com"], "ExposeHeaders": [] } ]
- 确认IAM权限配置
确认你生成预签名URL所用的AK/SK对应的IAM用户,拥有对应存储桶的s3:PutObject权限,示例IAM权限策略如下:
- 确认IAM权限配置
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::atlasfitness-progress/*" } ] }
内容的提问来源于stack exchange,提问作者Gonsa02
相关产品推荐
相关产品推荐

