2009-11-03 18 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 

その後、私のrakeタスク、私はこれを行うには:

# 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(path)を使用すると、望ましくない状況につながります。 PaperclipはFile.newインスタンスを閉じることはありません。このため、多くの添付ファイルを処理する際に「開いているファイルが多すぎます」などのエラーが発生する可能性があります。正しいコードは でなければなりません。f = File.new(logo_path) client.logo = f f.close' –

+2

非常に良いコメントです。少数のファイルで非常に小さなタスクでこれを使用したので、私はその問題にぶつかりませんでした。私は私のソリューションを更新しました - 私は手動で閉じるのではなく、File.open を可能な限り使用する方が好きです。 – kikito

11

ペーパークリップに保存したファイルは、フォームから直接アップロードする必要はありません。

私は、ウェブクローラ結果からのURLからファイルを保存するプロジェクトにペーパークリップを使用しています。私はどのように電子メールの添付ファイルを取得するのか分かりません(サーバーのローカルファイルシステム上にありますか?あなたのアプリケーションはGmailのような電子メールアプリケーションですか)、ファイルストリームを得ることができる限り(open(URI.parse(crawl_result))私の場合...)あなたはhas_attached_fileとマークされたモデルフィールドにそのファイルを添付することができます。

Easy Upload via URL with Paperclipについてこのブログの記事は、私はこれを理解助けました。

今、元のブログ記事が使用できなくなった表示されませんので - ここでの要点は、ウェイバックマシンから引き出されます:

をこの例では、画像の添付ファイルを持っている写真のモデルを示しています。

私たちが使っている技術は、元のURLを格納するために使用され、あなたの添付ファイル、ため*_remote_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 

の人がファイルをアップロードするか、URLを提供できるように、我々は、:image_urlと呼ばれるtext_fieldを追加...

# 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のものを使用する必要があります。次に、before_validationコールバックを追加して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

これは、大きなファイルをダウンロードするのにかなりメモリを消費します。第2に、10KB未満のファイルに対してStringIOが返され、paperclipがコンテンツタイプの検証を行う場合、Stringにはコンテンツタイプがないため失敗します。 – maletor

関連する問題