Rails 6本地传Amazon S3正常,Railway生产环境报422错误求助
问题
本地环境将图片上传至Amazon S3完全正常,但部署到railway.app生产服务器时,出现不明原因的422错误,且已确认S3存储桶权限配置正确。
尝试两种上传方式均触发错误:
- 将图片附加到记录并保存时
- 调用
ActiveStorage::Blob.create_before_direct_upload!创建Blob时,代码如下:
blob = ActiveStorage::Blob.create_before_direct_upload!(filename: blob_args[:filename], byte_size: blob_args[:byte_size], checksum: blob_args[:checksum], content_type: blob_args[:content_type])
补充说明:该关联记录无任何验证规则。
自定义DirectUploadsController代码如下:
class DirectUploadsController < ActiveStorage::DirectUploadsController include ActionController::HttpAuthentication::Basic::ControllerMethods skip_before_action :verify_authenticity_token def create blob = ActiveStorage::Blob.create_before_direct_upload!(filename: blob_args[:filename], byte_size: blob_args[:byte_size], checksum: blob_args[:checksum], content_type: blob_args[:content_type]) render json: direct_upload_json(blob) end private def direct_upload_json(blob) blob.as_json(root: false, methods: :signed_id).merge(service_url: url_for(blob)).merge(direct_upload: { url: blob.service_url_for_direct_upload, headers: blob.service_headers_for_direct_upload }) end end
前端使用Angular 2向Rails API发送图片,本地正常,生产环境创建Blob或附加图片时均返回422,前端代码:
uploadFile = (name:any, the_attachment:any) => { // name is a string, the_attachment is a File object const upload = new DirectUpload( the_attachment, 'https://some-api.railway.app/rails/active_storage/direct_uploads', // This url is exposed by default in your app ); upload.create((error, blob) => { if (error) { console.log(error) } else { let signed_id = blob.signed_id; let request_body = { logo: signed_id } this.http.put("https://some-api.railway.app/api/v1/upload_logo/38", request_body).subscribe((resp)=>{ console.log(resp) }) } });
AWS CORS策略配置:
[ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "PUT", "POST", "DELETE", "GET" ], "AllowedOrigins": [ "https://some-app.up.railway.app/", "https://some-admin.netlify.app/", ], "ExposeHeaders": [] } ]
前端错误日志:
POST https://some-app.up.railway.app/rails/active_storage/direct_uploads 422 ... main.a7200f0b44d7afc6.js:1 Error creating Blob for "386-3863556_ruby-clipart-vector-ruby-programming-language-png-transparent.png". Status: 422
可能的解决方向
1. 检查生产环境ActiveStorage配置
- 确认railway.app上的环境变量
AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_REGION、AWS_BUCKET是否正确设置,无拼写错误或值缺失。 - 验证生产环境
storage.yml配置是否指向正确的S3服务,比如是否按需开启public: true,无多余配置项干扰。
2. 排查Blob创建的参数合法性
422错误多由参数不合法导致,可从以下几点排查:
- 查看Rails生产日志(railway.app控制台可获取),日志会明确标注422错误的具体触发原因,比如哪个参数未通过验证。
- 验证前端传递的
checksum是否为文件的SHA-256哈希Base64编码,确保生产环境中前端生成的checksum与后端计算一致。 - 确认
content_type是否符合S3允许的类型,无生产环境Rails额外限制的情况。
3. 修正CORS配置的域名格式
当前CORS配置中AllowedOrigins的域名末尾带斜杠,会导致匹配失败,修正为:
"AllowedOrigins": [ "https://some-app.up.railway.app", "https://some-admin.netlify.app" ],
S3对域名匹配严格,带斜杠与不带斜杠会被视为不同域名,修正后重新保存CORS配置。
4. 确认自定义控制器的参数获取逻辑
自定义DirectUploadsController需确保blob_args正确提取前端参数,添加强参数处理:
def blob_args params.require(:blob).permit(:filename, :byte_size, :checksum, :content_type) end
若参数未正确提取,会导致参数缺失触发422错误。
5. 验证railway.app与S3的网络连通性
在railway.app控制台执行curl命令测试S3连通性,比如:
curl https://your-bucket-name.s3.your-region.amazonaws.com
确认服务器无网络策略或防火墙限制S3访问。
内容的提问来源于stack exchange,提问作者thecoderg
相关产品推荐
相关产品推荐

