Renaming uploaded files with Carrierwave

后端 未结 6 800
我寻月下人不归
我寻月下人不归 2021-01-31 08:46

I\'m using Carrierwave to upload files, and I have it working.

My issue is attempting to change the name of the uploaded file.

In the generated uploader.rb there

相关标签:
6条回答
  • 2021-01-31 09:25

    To have a real unique filename (not almost unique) I recommend to use the uuid gem.

    in Gemfile add:

    gem 'uuid'
    

    in file_uploader.rb:

    def filename
      if original_filename
        if model && model.read_attribute(mounted_as).present?
          model.read_attribute(mounted_as)
        else
          @name ||= "#{mounted_as}-#{uuid}.#{file.extension}"
        end
      end
    end
    
    protected
    
    def uuid
      UUID.state_file = false
      uuid = UUID.new
      uuid.generate
    end
    
    0 讨论(0)
  • 2021-01-31 09:26

    To just make the record.id prefix the filename you can do the following:

    class MyUploader < CarrierWave::Uploader::Base
    
      storage :file
    
      def store_dir
        model.class.to_s.underscore.pluralize
      end
    
      def filename
        model.id ? "#{model.id}-#{original_filename}" : original_filename
      end
    
      def url
        "/#{store_dir}/#{model.id}-#{model.file_before_type_cast}"
      end
    end
    
    0 讨论(0)
  • 2021-01-31 09:28

    Here is the solution, how to change the name of the file, if store_dir already contains the file with the exact name:

      if File.exists?(Rails.root.join("documents/" + "#{file.filename}")) && !path.to_s.eql?(Rails.root.join("documents/" + original_filename).to_s)
        @name ||= File.basename(original_filename, '.*') + Digest::MD5.hexdigest(File.dirname(current_path)).from(25)
        "#{@name}.#{file.extension}"
      else
        "#{original_filename}"
      end
    

    Note: Rails.root.join("documents/") is defined as my store_dir.

    Hope it helps someone.

    0 讨论(0)
  • 2021-01-31 09:35

    From the Google Group:

    def filename
      @name ||= "#{secure_token}.#{file.extension}" if original_filename
    end
    
    private
    
    def secure_token
      ivar = "@#{mounted_as}_secure_token"
      token = model.instance_variable_get(ivar)
      token ||= model.instance_variable_set(ivar, ActiveSupport::SecureRandom.hex(4))  
    end
    
    0 讨论(0)
  • 2021-01-31 09:39

    Well, another problem with your random filename generator is that it's possible to have collisions isn't it? You could possibly generate a filename that was already generated. One way to go about it would be to somehow generate a hash based on unique properties of the image, like file path. An example, from the carrierwave group:

    def filename 
      if original_filename 
        @name ||= Digest::MD5.hexdigest(File.dirname(current_path))
        "#{@name}.#{file.extension}"
      end
    end
    

    This will create an MD5 hash based on the current path and then append the original file's extension to it.

    Edit: The carrierwave wiki added an entry with a few methods on how to create random and unique filenames for all versioned files.

    0 讨论(0)
  • 2021-01-31 09:48

    The other solution looks good, but how I did it then was to have a hook that created a random string for a new name on instance creation, then:

     def filename
        "#{model.randomstring}.#{model.image.file.extension}"
     end
    

    in the uploader.

    That worked, putting the random name generation as part of the model, then having carrierwave use that.

    I am curious which is faster, more effective, reasonable, sound, etc.

    0 讨论(0)
提交回复
热议问题