2010-11-03 18 views
13

J'ai un fichier Rake, qui lit le contenu via HTTP et je veux utiliser Paperclip pour stocker le contenu chargé sur Amazon S3. Cela fonctionne correctement lorsque je fournis un fichier local, mais je voudrais définir le contenu comme une chaîne et définir le type de contenu manuellement.Comment utiliser Paperclip sans un fichier, juste avec une chaîne?

Ce qui suit ne fonctionne pas. Aucune erreur est émise, l'entrée de la base de données est mise à jour, mais aucun fichier est créé dans S3:

p.attachment = "Test" 
p.attachment_file_name = "test.txt" 
p.attachment_content_type = "text/plain" 
p.attachment_file_size = "Test".size 
p.attachment_updated_at = Time.now 
p.save 

Je suppose que je pourrais écrire un fichier temporaire avec mon contenu, mais ce serait une solution assez inefficace.

Répondre

2

Non, vous devez créer un fichier avec votre chaîne.

Il suffit de regarder le code source Paperclip: https://github.com/thoughtbot/paperclip/blob/master/lib/paperclip/attachment.rb#L77 et https://github.com/thoughtbot/paperclip/blob/master/lib/paperclip/iostream.rb#L5

lorsque vous attribuez quelque chose en utilisant my_model.attachment =, Paperclip veut un objet fichier.

+0

C'est malheureux. Pensez-vous que je devrais utiliser autre chose que Paperclip alors? Je voudrais garder la chance de passer de S3 au système de fichiers facilement, mais je n'ai pas de téléchargement de fichiers utilisateur, donc Paperclip pourrait être le mauvais choix. – Jan

+1

avez-vous regardé carrierwave: https://github.com/jnicklas/carrierwave qui semble une excellente alternative ... –

8

Il est un peu tard mais je l'a retiré en créant un fichier temporaire en utilisant des rails ruby ​​1.9.2 3.1

file = Tempfile.new(["file_name", '.txt']) 
file.write("my test string".force_encoding('utf-8')) 
p.attachment = file 
+0

brillant .. Je ne sais pas pourquoi cela fonctionne, mais cela fonctionne. –

+0

cela créera en fait un fichier ... https://ruby-doc.org/stdlib-1.9.3/libdoc/tempfile/rdoc/Tempfile.html – olivervbk

40

Pour éviter jonchant le système de fichiers avec des fichiers temporaires, vous pouvez utiliser StringIO comme dans:

p.attachment = StringIO.new(your_string) 
+1

Grande petite solution de contournement. Une fois que vous faites cela, définissez votre nom de fichier de pièce jointe avec 'p.attachment_file_name = 'test.txt' et vous êtes tous ensemble. –

0

similaires à Aarons mais avec la méthode de bloc approprié tel que suggéré par Ruby:

... on devrait toujours appeler unlink ou fermer dans un bloc assurer.

file = Tempfile.new('test.txt') 

begin 
    file.write("Test") 

    p.attachment = file 
    p.save    

    # Whatever else you might need to do with the TempFile. 

ensure 
    file.close 
    file.unlink # Deletes the temp file. 
end 
3

Pour les deux et carierwave paperclip Je finissent par créer une classe comme ça. Il a deux méthodes nécessaires pour simuler un téléchargement de fichier qu'ils aiment voir.

class FakeFileIO < StringIO 
    attr_reader :original_filename 
    attr_reader :path 

    def initialize(filename, content) 
    super(content) 
    @original_filename = File.basename(filename) 
    @path = File.path(filename) 
    end 
end 

fonctionne comme un rêve