Файл, сохраненный в Paperclip, не может быть загружен непосредственно через форму.
Я использую Paperclip в проекте для сохранения файлов из URL-адресов из результатов веб-поиска. Я не уверен, как вы получите вложения электронной почты (они находятся в локальной файловой системе сервера? Является ли ваше приложение почтовым приложением, таким как GMail?), Но до тех пор, пока вы можете получить поток файлов (через что-то вроде open(URI.parse(crawl_result))
в мой случай ...) вы можете прикрепить этот файл к полю вашей модели, помеченному has_attached_file
.
Это сообщение в блоге о
Easy Upload via URL with Paperclip помогло мне понять это. не
Поскольку теперь появляется оригинальный пост в блоге больше не доступен - вот суть его вытащили из машины Вайбак:
Этот пример показывает, фотомоделью, которая имеет прикрепление изображения.
Используемая техника требует добавления столбца *_remote_url
(строка) для вашего вложения, которое используется для хранения исходного URL-адреса. Итак, в этом случае нам нужно добавить столбец с именем image_remote_url
в таблицу фотографий.
# 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
Ничего особенного не требуется для контроллера ...
# 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
В форме, мы добавим text_field называется :image_url
, чтобы люди могли загрузить файл или предоставить 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 %>
Мягкий материал находится в Фотомодели. Нам нужно require open-uri
, добавьте attr_accessor :image_url
и сделайте обычный материал has_attached_file
. Затем добавим обратный вызов , чтобы загрузить файл в атрибуте image_url
(если предоставлено) и сохранить исходный URL как image_remote_url
. Наконец, мы делаем validates_presence_of :image_remote_url
, что позволяет нам избавиться от многих исключений, которые могут быть подняты при попытке загрузить файл.
# 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
Все будет работать в обычном режиме, в том числе создание миниатюр и т.д. Плюс, так как мы делаем все сложные вещи в модели, «загрузка» файл через URL работает внутри скрипта/консоли а также:
$ 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">
Использование File.new (путь) приводит к нежелательным ситуациям. Скрепка никогда не закрывает экземпляр File.new, и это может привести к ошибкам, таким как «Слишком много открытых файлов» при обработке большого количества вложений. Правильный код должен быть 'f = File.new (logo_path) client.logo = f f.close' –
Очень хороший комментарий. Я не попал в эту проблему, потому что использовал это по очень маленькой задаче с небольшим количеством файлов. Я обновил свое решение - я предпочитаю использовать File.open, когда это возможно, вместо закрытия вручную. –
kikito