迁移至AWS Lambda与Vercel后,Django+Next.js前端无法上传图片至S3
问题排查与解决方案
针对你迁移后前端无法上传图片(Postman/Admin正常)、触发S3 HeadObject 400错误的问题,结合Lambda与S3跨区域的情况,给出以下排查方向和解决方法:
1. 修正django-storages的跨区域配置
Lambda与S3不在同一区域时,必须明确指定S3的区域和Endpoint,否则django-storages可能会用默认区域发起请求,导致400错误。
在Django的settings.py中补充/修正以下配置:
# 替换为你的S3桶实际区域 AWS_S3_REGION_NAME = 'ap-southeast-1' # 对应区域的S3 Endpoint AWS_S3_ENDPOINT_URL = f'https://s3.{AWS_S3_REGION_NAME}.amazonaws.com' # 你的S3桶名称 AWS_STORAGE_BUCKET_NAME = 'your-bucket-name'
同时检查Lambda的IAM角色权限,必须包含s3:HeadObject、s3:PutObject等操作,资源范围要覆盖目标S3桶(如arn:aws:s3:::your-bucket-name/*)。
2. 调整前端FormData的请求头设置
前端手动设置的请求头可能导致FormData解析异常,进而触发S3操作错误:
- 不要手动设置
Content-Type为multipart/form-data:FormData会自动生成包含boundary的正确Content-Type,手动设置会破坏格式,导致后端无法解析文件字段。 - 确认
img变量是标准File对象:在submit函数开头添加调试代码,检查img的类型:console.log('Upload file:', img); // 确保输出是File类型,包含name、size等属性 - 若Django启用CSRF验证,需添加CSRF Token到请求头:
// 从cookie中获取CSRF Token function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } // 添加到请求头 myHeaders.append("X-CSRFToken", getCookie('csrftoken'));
3. 排查S3桶的CORS配置
虽然后端调用S3主要依赖IAM权限,但仍需确认S3桶的CORS配置是否允许相关操作(避免预请求或隐性限制):
<CORSConfiguration> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <!-- 可限制为Vercel域名提升安全性 --> <AllowedMethod>GET</AllowedMethod> <AllowedMethod>POST</AllowedMethod> <AllowedMethod>PUT</AllowedMethod> <AllowedHeader>*</AllowedHeader> </CORSRule> </CORSConfiguration>
4. 升级django-storages版本
旧版本的django-storages可能存在跨区域S3请求的bug,尝试升级到最新稳定版:
pip install --upgrade django-storages[boto3]
内容的提问来源于stack exchange,提问作者Daljit Singh
相关产品推荐
相关产品推荐

