Search code examples
ruby-on-railspaperclipproduction-environment

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...


Solution

  • 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:

    1. Install the apache module mod-xsendfile
    2. Comment out that line and let Rails send the files instead of Apache, like it does in development mode.