2010-12-14 23 views
30

Uso Carrierwave per caricare file e l'ho fatto funzionare.Rinominare i file caricati con Carrierwave

Il mio problema sta tentando di modificare il nome del file caricato.

Nella generato uploader.rb c'è un metodo penso dovrei usare

def filename 
    "something.jpg" if original_filename 
    basename = "what"+orginal_filename if original_filename, works 
    basename = (0...8).map{65.+(rand(25)).chr}.join if original_filename # will create a random name for each version, e.g. the orginal, the thumb, and the filename in the db, useless 
end 

Non riesco ad accedere oggetti come 'estensione' o 'content_type' in sanitized_file.rb, quindi questo è un po 'oltre il mio attuale livello di abilità in questo momento.

Eventuali suggerimenti o esercizi per fare ciò, ovvero generare il nome file per un file caricato che funziona come predefinito per il gestore di telefonia mobile (non eseguire nulla, ma continua con ciascuna versione)? Sembra che dovrebbe essere abbastanza semplice ma sono inciampato su questo.

+2

io non capisco il codice con commenti/code tutti mescolati. Puoi modificarlo? – lulalala

risposta

34

Bene, un altro problema con il generatore di nome casuale è che è possibile avere collisioni no? È possibile generare un nome file già generato. Un modo per farlo sarebbe generare in qualche modo un hash basato su proprietà uniche dell'immagine, come il percorso del file. Un esempio dal carrierwave group:

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

questo creerà un hash MD5 in base al percorso corrente e quindi aggiungere l'estensione del file originale ad esso.

Edit: Il wiki carrierwave ha aggiunto un entry con alcuni metodi su come creare nomi di file casuali e unici per tutti i file di versione.

+1

Questa è sicuramente la migliore risposta. Gli hash sono la soluzione giusta a questo problema. –

+2

Assumendo uno ha un compito rastrello che entra e cancella i file temporanei, non è la probabilità di una collisione utilizzando solo File.dirname (current_path) piuttosto alto? Penso che una soluzione migliore potrebbe essere quella di usare created_at in combinazione con il percorso. – saneshark

+0

Che ne dici di usare un uuid? @name = SecureRandom.uuid – Brady

1

L'altra soluzione sembra buono, ma come ho fatto allora era di avere un gancio che ha creato una stringa casuale di un nuovo nome sulla creazione dell'istanza, quindi:

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

nel uploader.

Ciò ha funzionato, inserendo la generazione del nome casuale come parte del modello, quindi utilizzando carrierwave.

Sono curioso che è più veloce, più efficace, ragionevole, suono, ecc

+3

Dovresti contrassegnarlo come corretto allora. –

1

Dal 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 
1

fare solo il prefisso record.id il nome del file è possibile effettuare le seguenti operazioni :

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 
4

per avere un vero e proprio nome di file unico (non quasi unico) vi consiglio di usare la gemma uuid.

in Gemfile aggiungere:

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

dovrei aggiungere questo nell'uploader? –

+0

sì all'autore del caricamento – ramigg

0

ecco la soluzione, come cambiare il nome del file, se store_dir contiene già il file con il nome esatto:

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 

Nota: Rails.root.join("documents/") è definito come il mio store_dir.

Spero che aiuti qualcuno.

Problemi correlati