2009-11-03 5 views
31

У меня был быстрый вопрос. Можно ли сохранить файл без фактической загрузки его через форму?Сохранение файлов с помощью Paperclip без загрузки

Например, предположим, что я ищу приложения из электронных писем, и я хочу сохранить их с помощью скрепки. Как мне это сделать? Должен ли я вручную вызывать файл save_file (или что-то подобное) где-нибудь?

Любая помощь была бы высоко оценена!

ответ

46

у меня есть реки задача, которая загружает изображения (клиентские логотипы) из каталога непосредственно на parperclip. Вы, вероятно, можете адаптировать его к вашим потребностям.

Это моя упрощенная модель Клиент:

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 

Тогда на моей передней задачи я делаю это:

# 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 

С уважением!

+4

Использование File.new (путь) приводит к нежелательным ситуациям. Скрепка никогда не закрывает экземпляр File.new, и это может привести к ошибкам, таким как «Слишком много открытых файлов» при обработке большого количества вложений. Правильный код должен быть 'f = File.new (logo_path) client.logo = f f.close' –

+2

Очень хороший комментарий. Я не попал в эту проблему, потому что использовал это по очень маленькой задаче с небольшим количеством файлов. Я обновил свое решение - я предпочитаю использовать File.open , когда это возможно, вместо закрытия вручную. – kikito

11

Файл, сохраненный в 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"> 
+0

Sweet! Большое спасибо! –

+0

@Nate Спасибо за этот комментарий. Похоже, что ссылка больше не работает? –

+0

Это довольно интенсивная память для загрузки больших файлов. Во-вторых, StringIO возвращается для файлов размером менее 10 КБ, и если paperclip делает проверку типа содержимого, это не будет работать, потому что строки не имеют типов контента. – maletor

Смежные вопросы