2010-11-09 14 views
1

J'ai des flux d'octets sur le serveur que je voudrais attacher à une classe de modèle avec Paperclip, et j'aimerais pouvoir spécifier le nom qu'ils ont enregistré sur le système de fichiers. Parce que j'ai beaucoup de ces fichiers entrants, je préfère être en mesure de les créer comme Tempfiles de sorte que je n'ai pas à vous soucier des collisions de noms et de les supprimer manuellement et autres. C'est ce que je fais:Comment puis-je spécifier un nom de fichier pour ma pièce jointe avec Paperclip?

desired_file_name = 'foo.txt' 
Tempfile.open([File.basename(desired_file_name), File.extname(desired_file_name)]) do |tf| 
    tf.write(content_stream) 
    tf.rewind 
    model_obj.paperclip_attachment = tf 
end 

Cela marche plutôt bien. Le seul problème est, ma pièce jointe Paperclip se termine avec un nom de fichier temp comme foo.txt.201029392u-gyh-foh96y.txt. Alors, comment puis-je dire à Paperclip de quoi enregistrer mon fichier? L'appel au model_obj.paperclip_attachment_file_name = desired_file_name ne fonctionne pas. Le champ DB est enregistré sous ce nom, mais sur le système de fichiers, j'ai toujours ce nom de fichier temporaire.

Répondre

7

Je pense que vous pouvez définir votre propre interpolation interpolation pour ce faire. Vous pouvez ensuite attacher le fichier normalement. Par exemple:

# config/initializers/paperclip.rb 
Paperclip.interpolates :custom_filename do |attachment, style| 
    # Generate your desired file name here. 
    # The values returned should be able to be regenerated in the future because 
    # this will also be called to get the attachment path. 

    # For example, you can use a digest of the file name and updated_at field. 
    # File name and updated_at will remain the same as long as the file is not 
    # changed, so this is a safe choice. 
    SHA1.sha1("#{attachment.original_filename}-#{attachment.updated_at}") 
end 

# app/models/post.rb 
class Post < ActiveRecord::Base 
    has_attached_file :attachment, 
    :path => ':rails_root/public/system/:class/:attachment/:id/:style/:custom_filename', 
    :url => '/system/:class/:attachment/:id/:style/:custom_filename' 
end 

Notez que cela modifie uniquement le nom de fichier dans le système de fichiers. model.attachment_file_name ou model.attachment.original_filename conserve toujours le nom de fichier d'origine.

+0

Merci, cela a fonctionné! La seule chose que je ne comprends pas bien (et que je n'ai pas implémentée) c'est pourquoi vous avez suggéré d'utiliser la fonction de hachage. Je souhaite conserver le nom de fichier souhaité. Le chemin du fichier, qui inclut l'identifiant, doit garantir l'unicité. – Jeff

+0

La fonction de hachage est de rendre le nom de fichier impossible à deviner, donc les gens ne peuvent pas simplement deviner les URL (attachement/1, pièce jointe/2, etc) et télécharger tous les fichiers. Utiliser le nom de fichier id plus devrait également aboutir à la même chose, mais l'avantage d'utiliser un hachage pour moi est qu'il n'y a pas de caractères qui doivent s'échapper d'une URL. – htanata