React/JS调用S3预签名URL上传图片报403 Forbidden错误求助
解决React中使用S3预签名URL上传403 Forbidden的问题
核心问题分析
你的Python代码是直接上传二进制文件流,而React中最初用FormData或错误处理请求体的方式,导致请求内容(包括请求体结构、请求头)和预签名URL生成时的验证条件不匹配,S3签名验证失败返回403。
具体解决方案
1. 修正上传请求代码
不要使用FormData,直接将File对象作为请求体发送,同时确保请求头和预签名URL生成时的参数一致:
// on submit: const options = { method: 'put', body: img, // 直接传入File对象,无需包装成FormData // 仅当预签名URL生成时指定了Content-Type,才添加这个头,值要和文件的type完全一致 headers: { 'Content-Type': img.type } }; const res = await fetch(psurl, options);
2. 匹配预签名URL的生成条件
- 如果生成预签名URL时指定了
Content-Type参数(比如Python生成时设置了ContentType),上传请求的Content-Type头必须和这个值完全一致,不能多也不能少。 - 如果生成预签名URL时没有指定
Content-Type,则上传请求不要添加这个头,或者确保头信息和生成时的默认条件匹配。
3. 检查S3存储桶的CORS配置
浏览器环境下的跨域请求需要S3配置正确的CORS规则,允许你的React域名发起PUT请求:
<CORSConfiguration> <CORSRule> <AllowedOrigin>https://your-react-app-domain.com</AllowedOrigin> <!-- 替换为你的域名,或用*测试 --> <AllowedMethod>PUT</AllowedMethod> <AllowedHeader>*</AllowedHeader> <!-- 允许所有头,或指定需要的Content-Type等 --> <MaxAgeSeconds>3000</MaxAgeSeconds> </CORSRule> </CORSConfiguration>
注意:生产环境不要用*作为AllowedOrigin,仅用于测试场景。
为什么之前的方式失败?
FormData会将请求体包装成multipart/form-data格式,包含额外的边界标识和字段信息,这和Python直接上传的二进制流完全不同,S3的签名验证会因为请求体不匹配而拒绝请求。- 直接传
img["file"]是错误操作,img本身就是File对象,无需额外取file属性。
内容的提问来源于stack exchange,提问作者Ori.B
相关产品推荐
相关产品推荐

