Rails 3 app + paperclip gem + production mode = download of empty files
I've installed the paperclip gem for a Rails 3 开发者_运维问答application. Everything works fine in development mode. However, when running in production mode, if I upload a file and then try to download it again, it downloads a file with the correct name and extension, but it is an empty file. When looking on the server, the file does get uploaded and is in the correct directory. (I have an "uploads" folder in my application root.)
Anyone had this happen?
My model:
# app/models/document.rb
class Document < ActiveRecord::Base
belongs_to :kase
has_attached_file :document, :path => (Rails.root + "uploads/:class/:kase_id/:id").to_s, :url => ":class/:id"
validates_attachment_presence :document
validates_attachment_content_type :document, :content_type => [
'application/pdf',
'image/png',
'image/jpeg',
'image/pjpeg',
'text/plain'
]
end
My controller:
# app/controllers/documents_controller.rb
class DocumentsController < ApplicationController
respond_to :html
before_filter :initialize_kase # Sets the @kase instance
def show
@document = @kase.documents.find(params[:id])
send_file @document.document.path, :filename => @document.document_file_name, :content_type => @document.document_content_type
end
end
And my initializer (setting the :kase_id placeholder used in has_attached_file above:
# config/initializers/paperclip.rb
Paperclip.interpolates('kase_id') do |attachment, style|
"kases/#{attachment.instance.kase.id.to_s}"
end
I should probably mention, too, that I am accessing this as a nested controller (/kases/XX/documents/XX). Not sure if that has an effect or not...
If you are using Apache and Passenger, (possibly other servers as well) and have the line:
config.action_dispatch.x_sendfile_header = "X-Sendfile"
in your production.rb env file, then you have two options:
- Install the apache module mod-xsendfile
- Comment out that line and let Rails send the files instead of Apache, like it does in development mode.
Are you carrying over the uploads directory each time you deploy your app to production? Assuming that you're using capistrano (or similar) for deployment, each time you deploy you might be creating a new uploads directory in the newly-deployed release directory. In that case, the previously-uploaded files are residing in older deployed releases (if you didn't delete those) and would no longer be accessible to your app.
You want to create e.g. shared/uploads
directory that is symlinked into your app on each deploy.
精彩评论