Last Updated: September 09, 2019
·
7.78K
· codenamev

Custom file names with Carrierwave and Amazon S3

With the following uploader app/uploaders/document_uploader.rb:

class DocumentUploader < CarrierWave::Uploader::Base
  storage :fog

  def store_dir
      "uploads/#{Rails.env}/#{model.class.to_s.underscore.pluralize}/#{mounted_as}/#{model.id}"
    end
  end

  def store_path(for_file = filename)
    "uploads/#{Rails.env}/#{model.class.to_s.underscore.pluralize}/#{mounted_as}/#{model.id}/#{for_file}"
  end

  def filename(uploaded_file = file)
    if uploaded_file.present?
        "Document with custom title ##{model.id}.#{uploaded_file.extension}"
    end
  end
end

Mounted in a model like so:

class Attachment < ActiveRecord::Base
  mount_uploader :document, DocumentUploader

  # these methods fix the filename persistance issue
  def read_uploader(column)
    self[column]
  end

  def write_uploader(column, identifier)
    self[column] = identifier
  end
end

Configuring carrierwave with S3:

CarrierWave.configure do |config|
  config.fog_credentials = {
    :provider               => 'AWS',
    :aws_access_key_id      => 'replace-this-with-your-access-key-id',
    :aws_secret_access_key  => 'replace-this-with-your-secret-access-key'
  }
  config.fog_directory  = 'rename-this-to-a-custom-directory-for-your-app'
  config.fog_public     = false
  config.fog_attributes = {'Cache-Control'=>'max-age=300000000'}
  config.cache_dir = "#{Rails.root}/tmp/uploads"
end

Say we uploaded a file named "JunkName for a file.pdf" in the Development environment,
you should now get a custom file saved in S3 like: uploads/development/attachments/document/3/Document with custom title #3.pdf

The read_uploader and write_uploader functions in your model may be a bug with Carrierwave... but I'm waiting to see: https://github.com/carrierwaveuploader/carrierwave/issues/1132

Until then, enjoy. Hunting this down was not fun.