使用boto3生成S3预签名Post时Content-Type重复问题解决
解决S3预签名Post上传后Content-Type重复问题
在用boto3生成S3预签名Post实现前端上传图片时,上传后的文件Content-Type变成了image/png,image/png,出现重复值。相关代码如下:
后端Python(boto3)代码
s3_client = boto3.client('s3') response = s3_client.generate_presigned_post( "bucket", "logo", Fields={ "Content-Type": "image/png" }, Conditions=[ ["starts-with", "$Content-Type", "image/"], ], ExpiresIn=3600 )
预签名返回示例
{ "url": "https://s3.amazonaws.com/bucket", "fields": { "Content-Type": "image/png", "key": "logo", "AWSAccessKeyId": "ABC", "policy": "blahblah", "signature": "XYZ123" } }
前端JavaScript代码
const formData = new FormData(); for (const key in json.fields) { formData.append(key, json.fields[key]); } formData.append("file", image); return fetch(json.url, { method: "POST", body: formData });
问题原因
出现重复是因为FormData里同时包含了预签名返回的Content-Type字段,以及file对象自身携带的Content-Type,S3会将这两个值合并成逗号分隔的形式。
解决方法
方案1:固定Content-Type(仅允许image/png)
- 修改后端代码:移除
Fields里的Content-Type,同时把Conditions改为精确匹配image/png,确保只有该类型的文件能上传:
s3_client = boto3.client('s3') response = s3_client.generate_presigned_post( "bucket", "logo", Fields={ # 移除Content-Type字段 }, Conditions=[ ["eq", "$Content-Type", "image/png"], ], ExpiresIn=3600 )
- 修改前端代码:循环添加字段时跳过
Content-Type,同时可以手动指定文件的Content-Type(或直接使用文件自身的):
const formData = new FormData(); for (const key in json.fields) { if (key === "Content-Type") continue; formData.append(key, json.fields[key]); } // 手动指定类型,或直接用image本身的type formData.append("file", image, { type: "image/png" }); return fetch(json.url, { method: "POST", body: formData });
方案2:支持多种图片类型
如果需要允许所有图片类型上传,只需要调整后端和前端代码,不再手动添加Content-Type字段:
- 后端代码:移除
Fields里的Content-Type,保留starts-with的条件:
s3_client = boto3.client('s3') response = s3_client.generate_presigned_post( "bucket", "logo", Fields={ # 不指定Content-Type }, Conditions=[ ["starts-with", "$Content-Type", "image/"], ], ExpiresIn=3600 )
- 前端代码:同样跳过
Content-Type字段,直接上传文件,使用文件自身的Content-Type:
const formData = new FormData(); for (const key in json.fields) { if (key === "Content-Type") continue; formData.append(key, json.fields[key]); } formData.append("file", image); return fetch(json.url, { method: "POST", body: formData });
这样处理后,S3只会使用单一的Content-Type值,不会出现重复的情况。
内容的提问来源于stack exchange,提问作者timborden
相关产品推荐
相关产品推荐

