How to update/rename a carrierwave uploaded file?

喜欢而已 提交于 2019-12-03 03:48:39

I was able to get the following working, although I'm sure there is a more elegant way. I'd appreciate any comments on the following

*add this to app/uploaders/file_uploader.rb

def rename(new_name)
  sf = model.file.file
  new_path = File.join( File.dirname( sf.file ) , "#{new_name}#{File.extname( sf.file )}")
  new_sf = CarrierWave::SanitizedFile.new sf.move_to(new_path)
  model.file.cache!(new_sf)
  model.save!
  return model
end

Thanks!

I used this rake task for reprocessing uploaded images after modifying version settings (filename and image size) in my uploader file:

# Usage: rake carrierwave:reprocess class=Model
namespace :carrierwave do
  task :reprocess => :environment do

    CLASS = ENV['class'].capitalize
    MODEL = Kernel.const_get(CLASS)
    records = MODEL.all

    records.each do |record|
      record.photo.recreate_versions! if record.photo?
    end

  end
end

Notes:

  • Replace "photo" with whatever you named your uploader.
  • Rake tasks go in the lib/tasks folder.
  • This is using Active Record, not sure if Mongoid needs something different.

Based on @user892583, I worked on it and came up with a simpler solution:

def rename!(new_name)
  new_path = File.join(File.dirname(file.file), new_name)
  file.move_to(new_path)
end

I did this with this way:

  def filename
    if !cached? && file.present?
      new_filename = 'foobar'
      new_path = File.join(File.dirname(file.path), new_filename)
      file.move_to(new_path)
      recreate_versions!
      new_filename
    else
      super
    end
  end

I think this is only right way to rename file.

The most efficient way to do this is to just move the existing S3 object (assuming your storage layer is S3):

def rename(new_name)
  bucket_name = "yourapp-#{Rails.env}"
  resource = Aws::S3::Resource.new
  bucket = resource.bucket(bucket_name)
  object = bucket.object(path)
  new_filename = "#{new_name}#{File.extname(path)}"
  new_path = File.join(File.dirname(path), new_filename)
  object.move_to(bucket: bucket_name, key: new_path)

  model.update_column(mounted_as, new_filename)
  model.reload

  # Now call `recreate_versions!(*versions.keys)`
  # if you want versions updated. Explicitly passing
  # versions will prevent the base version getting
  # reuploaded.

  model
end

This is using the aws-sdk-s3 gem.

I store image files -- and derivative versions -- in an S3-compatible solution. I use Carrierwave (1.2.2) with the "fog-aws" gem (3.0.0) on Rails 5.1. The following public method works for me when added to the "uploader" file (eg, app/uploaders/example_uploader.rb):

class ExampleUploader < CarrierWave::Uploader::Base
  <snip>

  # Renames original file and versions to match given filename
  #
  # Options:
  # * +:keep_original+ - Do not remove original file and versions (ie, copy only)
  def rename(new_filename, options = {})
    return if !file || new_filename == file.filename
    target = File.join(store_path, new_filename)
    file.copy_to(target)
    versions.keys.each do |k|
      target = File.join(store_path, "#{k}_#{new_filename}")
      version = send(k).file
      version.copy_to(target)
    end
    remove! unless options[:keep_original]
    model.update_column(mounted_as, new_filename) && model.reload
  end

  <snip>
end
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!