2009-11-03 5 views
31

j'ai eu une petite question. Est-il possible de sauvegarder un fichier sans le télécharger via un formulaire?Enregistrement de fichiers à l'aide Paperclip sans télécharger

Par exemple, disons que je regarde les pièces jointes des e-mails, et je veux les enregistrer à l'aide d'un trombone. Comment puis-je faire cela? Dois-je manuellement appeler un save_file (ou quelque chose de similaire) quelque part?

Toute aide serait grandement appréciée!

Répondre

46

J'ai une tâche de râteau qui charge les images (logos client) à partir d'un répertoire directement sur parperclip. Vous pouvez probablement l'adapter à vos besoins.

Ceci est mon modèle client simplifié:

class Client < ActiveRecord::Base 
    LOGO_STYLES = { 
    :original => ['1024x768>', :jpg], 
    :medium => ['256x192#', :jpg], 
    :small => ['128x96#', :jpg] 
    } 

    has_attached_file :logo, 
    :styles => Client::LOGO_STYLES, 
    :url => "/clients/logo/:id.jpg?style=:style" 
    attr_protected :logo_file_name, :logo_content_type, :logo_size 

Puis sur ma tâche Rake Je fais ceci:

# the logos are in a folder with path logos_dir 
Dir.glob(File.join(logos_dir,'*')).each do |logo_path| 
    if File.basename(logo_path)[0]!= '.' and !File.directory? logo_path 

    client_code = File.basename(logo_path, '.*') #filename without extension 
    client = Client.find_by_code(client_code) #you could use the ids, too 
    raise "could not find client for client_code #{client_code}" if client.nil? 

    File.open(logo_path) do |f| 
     client.logo = f # just assign the logo attribute to a file 
     client.save 
    end #file gets closed automatically here 
    end 
end 

Cordialement!

+4

L'utilisation de File.new (chemin) conduit à des situations indésirables. Paperclip ne ferme jamais l'instance File.new et cela peut conduire à des erreurs telles que "Trop de fichiers ouverts" lors du traitement de beaucoup de pièces jointes. Le code correct devrait être 'f = File.new (logo_path) client.logo = f f.close' –

+2

Très bon commentaire. Je n'ai pas rencontré ce problème parce que je l'ai utilisé sur une très petite tâche avec un petit nombre de fichiers. J'ai mis à jour ma solution - Je préfère utiliser File.open autant que possible au lieu de fermer manuellement. – kikito

11

Le fichier enregistré dans Paperclip ne doit pas être téléchargé directement via un formulaire.

J'utilise Paperclip dans un projet pour enregistrer des fichiers à partir d'URL à partir des résultats de webcrawler. Je ne sais pas comment vous obtiendriez les pièces jointes (sont-elles sur le système de fichiers local du serveur? Votre application est-elle une application de messagerie comme GMail?) Mais aussi longtemps que vous pouvez obtenir un flux de fichier (via quelque chose comme open(URI.parse(crawl_result)) mon cas ...) vous pouvez attacher ce fichier à votre champ de modèle qui est marqué has_attached_file.

Ce billet de blog sur Easy Upload via URL with Paperclip m'a aidé à comprendre cela.

Comme il apparaît maintenant le message blog n'est plus disponible - est ici l'essentiel de celui-ci tiré de la machine à remonter le temps:

Cet exemple montre un modèle de photo qui a une image en pièce jointe.

La technique que nous utilisons nécessite l'ajout d'une colonne *_remote_url (chaîne) pour votre pièce jointe, qui est utilisée pour stocker l'URL d'origine. Donc, dans ce cas, nous devons ajouter une colonne nommée image_remote_url la table des photos.

# db/migrate/20081210200032_add_image_remote_url_to_photos.rb 

class AddImageRemoteUrlToPhotos < ActiveRecord::Migration 
    def self.up 
    add_column :photos, :image_remote_url, :string 
    end 

    def self.down 
    remove_column :photos, :image_remote_url 
    end 
end 

Rien de spécial est nécessaire pour le contrôleur ...

# app/controllers/photos_controller.rb 

class PhotosController < ApplicationController 

    def create 
    @photo = Photo.new(params[:photo]) 
    if @photo.save 
     redirect_to photos_path 
    else 
     render :action => 'new' 
    end 
    end 

end 

Dans la forme, on ajoute un text_field appelé :image_url, afin que les gens peuvent télécharger un fichier ou fournir une URL ...

# app/views/photos/new.html.erb 

<%= error_messages_for :photo %> 
<% form_for :photo, :html => { :multipart => true } do |f| %> 
    Upload a photo: <%= f.file_field :image %><br> 
    ...or provide a URL: <%= f.text_field :image_url %><br> 
    <%= f.submit 'Submit' %> 
<% end %> 

la substance charnue est dans le modèle photo. Nous devons require open-uri, ajouter un attr_accessor :image_url, et faire les choses normales has_attached_file. Ensuite, nous ajoutons un rappel before_validation pour télécharger le fichier dans l'attribut image_url (si fourni) et enregistrer l'URL d'origine en tant que image_remote_url. Enfin, nous faisons un validates_presence_of :image_remote_url, ce qui nous permet de sauver des nombreuses exceptions qui peuvent être soulevées lors de la tentative de téléchargement du fichier.

# app/models/photo.rb 

require 'open-uri' 

class Photo < ActiveRecord::Base 

    attr_accessor :image_url 

    has_attached_file :image # etc... 

    before_validation :download_remote_image, :if => :image_url_provided? 

    validates_presence_of :image_remote_url, :if => :image_url_provided?, :message => 'is invalid or inaccessible' 

private 

    def image_url_provided? 
    !self.image_url.blank? 
    end 

    def download_remote_image 
    self.image = do_download_remote_image 
    self.image_remote_url = image_url 
    end 

    def do_download_remote_image 
    io = open(URI.parse(image_url)) 
    def io.original_filename; base_uri.path.split('/').last; end 
    io.original_filename.blank? ? nil : io 
    rescue # catch url errors with validations instead of exceptions (Errno::ENOENT, OpenURI::HTTPError, etc...) 
    end 

end 

Tout fonctionne normalement, y compris la création de vignettes, etc. De plus, puisque nous faisons tous les trucs dur dans le modèle, « ajout » un fichier via l'URL fonctionne à partir de script/console ainsi:

$ script/console 
Loading development environment (Rails 2.2.2) 
>> Photo.new(:image_url => 'http://www.google.com/intl/en_ALL/images/logo.gif') 
=> #<Photo image_file_name: "logo.gif", image_remote_url: "http://www.google.com/intl/en_ALL/images/logo.gif"> 
+0

Sweet! Merci beaucoup! –

+0

@Nate Merci pour ce commentaire. On dirait que le lien ne fonctionne plus? –

+0

Cela nécessite beaucoup de mémoire pour le téléchargement de fichiers volumineux. Deuxièmement, un StringIO est renvoyé pour les fichiers de moins de 10 Ko et si paperclip effectue la validation du type de contenu, cela échouera car les chaînes n'ont pas de type de contenu. – maletor

Questions connexes