Rails 5部署Heroku后AWS存储图片无法加载,报路由错误求助
Hey, let's tackle this issue step by step. The error you're seeing means your app is trying to serve images from the local /system path instead of directly from AWS S3, which is where you configured them to be stored. Here's what you can do to fix it:
1. Verify Paperclip's S3 Configuration in Production
First, make sure your config/environments/production.rb has the correct Paperclip defaults pointing to S3. It should look something like this:
config.paperclip_defaults = { storage: :s3, s3_credentials: { bucket: ENV['S3_BUCKET_NAME'], access_key_id: ENV['AWS_ACCESS_KEY_ID'], secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], s3_region: ENV['S3_REGION'] } }
Double-check that all these environment variables are set correctly on Heroku. Run heroku config in your terminal to confirm they exist and have the right values. If any are missing, add them with heroku config:set KEY=VALUE.
2. Reprocess Existing Image Attachments
Your older Dream records might still have local file paths stored in the database instead of S3 URLs. To update them, you'll need to reprocess the attachments:
- Open the Heroku Rails console with
heroku run rails c - Run this command to reprocess all images:
Dream.find_each do |dream| dream.image.reprocess! if dream.image.present? end
If you have a lot of records, consider adding a batch limit (like Dream.find_each(batch_size: 50)) to avoid timing out.
3. Check Your Model's Paperclip Mount
Ensure your Dream model isn't overriding the storage setting to use the local filesystem. The mount should look like this (without a storage: :filesystem option):
class Dream < ApplicationRecord has_attached_file :image, styles: { medium: "300x300>", thumb: "100x100>" } validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/ end
If you accidentally set storage: :filesystem somewhere, that would force Paperclip to look for local files instead of S3.
4. Validate S3 Bucket Permissions
- CORS Configuration: Make sure your S3 bucket's CORS policy allows requests from your Heroku app's domain. For public images, a basic policy might look like:
<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> <AllowedHeader>Authorization</AllowedHeader> </CORSRule> </CORSConfiguration> - IAM Permissions: The AWS user associated with your access keys should have permissions like
s3:PutObject,s3:GetObject, ands3:ListBucketfor your target bucket.
5. Confirm Gem Compatibility
You're using paperclip ~>5.2.1 and aws-sdk ~>1.59.0—this combination is compatible, but double-check your Gemfile.lock to ensure there are no conflicting dependencies. Run bundle install locally and commit the updated lockfile if needed, then redeploy to Heroku.
After going through these steps, your old images should start loading from S3 correctly, and new uploads should use the proper S3 URLs from the start.
内容的提问来源于stack exchange,提问作者Pipevel

