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:
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' –
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