AWS API Gateway配置二进制媒体类型遇CORS拦截、上传图片损坏问题
AWS API Gateway PUT方法上传图片到S3双异常修复方案
问题表现
两类异常的触发场景与报错信息:
- 在API Gateway的
Binary Media Types配置项添加*/*时,来自http://localhost:3001的前端请求被CORS策略拦截,报错如下:
Access to fetch at ‘some_invokation_request/my_s3_bucket/image.png’ from origin ‘http://localhost:3001’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: It does not have HTTP ok status.
- 移除
Binary Media Types中的*/*配置后,图片可成功上传至S3存储桶,但桶内存储的图片字节损坏、无法正常显示。
根因说明
- 配置
*/*为二进制媒体类型后,API Gateway会将所有请求(包括CORS预检使用的OPTIONS请求)识别为二进制载荷,不会正常处理OPTIONS请求的CORS响应逻辑,导致预检请求拿不到200状态码,触发浏览器跨域拦截。 - 未配置对应二进制媒体类型时,API Gateway默认将请求体按UTF-8文本做编码转换,二进制图片数据经过文本转码后字节错乱,最终存入S3的文件就会出现损坏、无法打开的问题。
修复步骤
- 调整二进制媒体类型配置
不要直接用*/*通配所有类型,仅在Binary Media Types中添加实际业务会用到的图片MIME类型即可,常用类型包括:image/pngimage/jpegimage/gifimage/webp
如果业务必须通配多类二进制格式,需按后续步骤单独处理OPTIONS预检请求。
- 在API Gateway层单独配置OPTIONS预检响应
不要依赖S3返回CORS响应头,直接在API Gateway层给对应上传资源添加OPTIONS方法,使用Mock集成固定返回CORS头:- 新建OPTIONS方法,集成类型选择「Mock」,无需对接后端S3
- 给方法添加200状态码的方法响应,配置以下必填响应头:
Access-Control-Allow-Origin:本地调试阶段填http://localhost:3001,生产环境替换为实际前端域名,不建议使用*避免跨域安全风险Access-Control-Allow-Methods:值设置为PUT, OPTIONSAccess-Control-Allow-Headers:值设置为请求实际携带的自定义头,常用值为Content-Type, Authorization, x-amz-acl, x-amz-content-sha256
- 在集成响应中做固定值映射,确保OPTIONS请求直接返回200状态和上述CORS头,不经过二进制处理逻辑。
- 配置PUT方法的内容处理规则
找到对接S3的PUT方法,进入集成请求设置页,将Content Handling参数设置为CONVERT_TO_BINARY,保证图片二进制数据不被文本转码,原样透传到S3。 - 重新部署API生效
所有配置修改完成后,将API重新部署到对应使用阶段,新配置才会正式生效。
内容的提问来源于stack exchange,提问作者Mike D Hovhannisyan
相关产品推荐
相关产品推荐

