2009-11-03 12 views
31

Ich hatte eine kurze Frage. Ist es möglich, eine Datei zu speichern, ohne sie tatsächlich über ein Formular hochzuladen?Dateien mit Paperclip ohne Upload speichern

Nehmen wir zum Beispiel an, ich schaue mir Anhänge von E-Mails an, und ich möchte sie mit einer Büroklammer speichern. Wie mache ich das? Muss ich manuell eine save_file (oder etwas ähnliches) irgendwo aufrufen?

Jede Hilfe wäre sehr willkommen!

Antwort

46

Ich habe eine Rake-Aufgabe, die Bilder (Client-Logos) aus einem Verzeichnis direkt auf Parperclip lädt. Sie können es wahrscheinlich an Ihre Bedürfnisse anpassen.

Das ist mein vereinfachte Client-Modell:

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 

Dann auf meiner Rake Aufgabe, die ich dies tun:

# 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 

Grüße!

+4

Die Verwendung von File.new (Pfad) führt zu unerwünschten Situationen. Paperclip schließt die Datei File.new nie und dies kann zu Fehlern wie "Zu viele geöffnete Dateien" führen, wenn viele Anhänge verarbeitet werden. Der korrekte Code sollte sein 'f = File.new (logo_path) client.logo = f f.close' –

+2

Sehr guter Kommentar. Ich habe dieses Problem nicht gefunden, weil ich dies bei einer sehr kleinen Aufgabe mit einer kleinen Anzahl von Dateien verwendet habe. Ich habe meine Lösung aktualisiert. Ich bevorzuge File.open wann immer es möglich ist, anstatt manuell zu schließen. – kikito

11

Die in Paperclip gespeicherte Datei muss nicht direkt über ein Formular hochgeladen werden.

Ich verwende Paperclip in einem Projekt, um Dateien von URLs aus Webcrawler-Ergebnissen zu speichern. Ich bin nicht sicher, wie Sie E-Mail-Anhänge erhalten würden (sind sie auf dem lokalen Dateisystem des Servers? Ist Ihre App eine E-Mail-App wie GMail?) Aber solange Sie einen Datei-Stream (über etwas wie open(URI.parse(crawl_result)) in Mein Fall ...) Sie können diese Datei an Ihr Modellfeld anhängen, das mit has_attached_file markiert ist.

Dieser Blogpost über Easy Upload via URL with Paperclip half mir, dies herauszufinden.

Da es nun die ursprüngliche Blog-Post erscheint, ist nicht mehr verfügbar - hier ist der Kern von ihm aus wayback Maschine gezogen:

Dieses Beispiel zeigt ein Foto-Modell, das eine Bild Anhang enthält.

Die von uns verwendete Technik erfordert das Hinzufügen einer *_remote_url (Zeichenfolge) -Spalte für Ihren Anhang, der zum Speichern der ursprünglichen URL verwendet wird. Also, in diesem Fall müssen wir eine Spalte mit dem Namen image_remote_url die Fotos Tabelle hinzufügen.

# 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 

ist nichts Besonderes für die Steuerung erforderlich ...

# 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 

In der Form, fügen wir ein text_field :image_url genannt, so dass die Leute eine URL auf eine Datei oder bieten hochladen ...

Das fleischige Zeug ist im Fotomodell. Wir müssen require open-uri, fügen Sie eine attr_accessor :image_url, und tun Sie die normalen has_attached_file Zeug. Dann fügen wir einen before_validation Callback hinzu, um die Datei im image_url Attribut (falls vorhanden) herunterzuladen und die ursprüngliche URL als image_remote_url zu speichern. Schließlich machen wir eine validates_presence_of :image_remote_url, die es uns ermöglicht, von den vielen Ausnahmen zu retten, die beim Versuch, die Datei herunterzuladen, ausgelöst werden können.

# 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 

Alles wird wie gewohnt arbeiten, einschließlich der Erstellung von Thumbnails etc. Plus, da wir alle der harten Sachen im Modell tun, „Hochladen“ eine Datei per URL funktioniert innerhalb Skript/Konsole auch:

+0

Süß! Danke vielmals! –

+0

@Nate Danke für diesen Kommentar. Sieht so aus, als ob der Link nicht mehr funktioniert? –

+0

Dies ist ziemlich speicherintensiv für das Herunterladen großer Dateien. Zweitens wird ein StringIO für Dateien mit weniger als 10 KB zurückgegeben, und wenn Paperclip die Überprüfung des Inhaltstyps durchführt, wird dies fehlschlagen, da Strings keine Inhaltstypen haben. – maletor

Verwandte Themen