Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify filename before saving with Carrierwave

I've an uploader where I've implement the #filename method to get a custom and unique filename but it looks like this method is ignored before saving the file (I'm uploading to rackspace with the fog gem)

Here is the uploader:

class MyImageUploader < CarrierWave::Uploader::Base
  include CarrierWave::RMagick

  ...

  def filename
    if original_filename.present?
      "#{secure_token}.#{file.path.split('.').last.downcase}"
    else
      super
    end
  end

  ...

  private

  def secure_token
    var = :"@#{mounted_as}_secure_token"
    model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
  end
end

And here is a test in the console (I'm testing an issue with large filenames that I thought was solved with the custom #filename method):

1.9.3-p392 :002 > f = File.open('/Users/myuser/Desktop/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.png')
 => #<File:/Users/myuser/Desktop/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.png>
1.9.3-p392 :003 > my_model_instance.image = f
Errno::ENAMETOOLONG: File name too long - /Users/myuser/app/tmp/uploads/20130509-1723-16769-8458/thumb_lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat4lolcat.png
  from /Users/myuser/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/fileutils.rb:1371:in `initialize'
  from /Users/myuser/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/fileutils.rb:1371:in `open'
  from /Users/myuser/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/fileutils.rb:1371:in `block in copy_file'
  from /Users/myuser/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/fileutils.rb:1370:in `open'
  from /Users/myuser/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/fileutils.rb:1370:in `copy_file'
  from /Users/myuser/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/fileutils.rb:477:in `copy_file'
  from /Users/myuser/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/fileutils.rb:396:in `block in cp'
  from /Users/myuser/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/fileutils.rb:1515:in `block in fu_each_src_dest'
  from /Users/myuser/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/fileutils.rb:1531:in `fu_each_src_dest0'
  from /Users/myuser/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/fileutils.rb:1513:in `fu_each_src_dest'
  from /Users/myuser/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/fileutils.rb:395:in `cp'
  from /Users/myuser/.rvm/gems/ruby-1.9.3-p392@app/gems/carrierwave-0.6.2/lib/carrierwave/sanitized_file.rb:205:in `copy_to'
  from /Users/myuser/.rvm/gems/ruby-1.9.3-p392@app/gems/carrierwave-0.6.2/lib/carrierwave/uploader/cache.rb:121:in `block in cache!'
  from /Users/myuser/.rvm/gems/ruby-1.9.3-p392@app/gems/carrierwave-0.6.2/lib/carrierwave/uploader/callbacks.rb:17:in `with_callbacks'
  from /Users/myuser/.rvm/gems/ruby-1.9.3-p392@app/gems/carrierwave-0.6.2/lib/carrierwave/uploader/cache.rb:112:in `cache!'
  from /Users/myuser/.rvm/gems/ruby-1.9.3-p392@app/gems/carrierwave-0.6.2/lib/carrierwave/uploader/versions.rb:231:in `block in cache_versions!'
  from /Users/myuser/.rvm/gems/ruby-1.9.3-p392@app/gems/carrierwave-0.6.2/lib/carrierwave/uploader/versions.rb:216:in `each'
  from /Users/myuser/.rvm/gems/ruby-1.9.3-p392@app/gems/carrierwave-0.6.2/lib/carrierwave/uploader/versions.rb:216:in `cache_versions!'
  from /Users/myuser/.rvm/gems/ruby-1.9.3-p392@app/gems/carrierwave-0.6.2/lib/carrierwave/uploader/callbacks.rb:18:in `block in with_callbacks'
  from /Users/myuser/.rvm/gems/ruby-1.9.3-p392@app/gems/carrierwave-0.6.2/lib/carrierwave/uploader/callbacks.rb:18:in `each'
  from /Users/myuser/.rvm/gems/ruby-1.9.3-p392@app/gems/carrierwave-0.6.2/lib/carrierwave/uploader/callbacks.rb:18:in `with_callbacks'
  from /Users/myuser/.rvm/gems/ruby-1.9.3-p392@app/gems/carrierwave-0.6.2/lib/carrierwave/uploader/cache.rb:112:in `cache!'
  from /Users/myuser/.rvm/gems/ruby-1.9.3-p392@app/gems/carrierwave-0.6.2/lib/carrierwave/mount.rb:315:in `cache'
  from /Users/myuser/.rvm/gems/ruby-1.9.3-p392@app/gems/carrierwave-0.6.2/lib/carrierwave/mount.rb:173:in `image='
  from /Users/myuser/.rvm/gems/ruby-1.9.3-p392@app/bundler/gems/carrierwave-mongoid-28a9b718d42b/lib/carrierwave/mongoid.rb:39:in `image='

So I think that I need to modify the filename before being saved in order to get the custom filename fully working because actually the file only is rename after being uploaded to Rackspace (only if the filename it's not so large)

like image 921
rdavila Avatar asked Oct 05 '22 04:10

rdavila


1 Answers

The upload is exploding during the caching step (which happens locally) rather than the saving step (which happens in fog). Reading the source, it looks like carrierwave has a method you can override to do just this: full_original_filename

If the problem you're trying to solve is to make the cached filename shorter, the following may work. If you want to change that filename later, you'll need to use the official solution for that in addition.

MAX_FILENAME_LENGTH = 64 # arbitrary limit, your milage may vary

def full_original_filename
  filename = super

  return filename if !filename.present?

  extension = File.extname(filename)
  basename = File.basename(filename, extension)[0...MAX_FILENAME_LENGTH]
  basename + extension
end
like image 72
Taavo Avatar answered Oct 13 '22 10:10

Taavo