2009-11-03 4 views
31

빠른 질문이있었습니다. 양식을 통해 파일을 실제로 업로드하지 않고 파일을 저장할 수 있습니까?업로드하지 않고 문서 클립을 사용하여 파일 저장

예를 들어 전자 메일의 첨부 파일을보고 클립 클립을 사용하여 첨부 파일을 저장하려고한다고 가정 해 봅시다. 어떻게해야합니까? 수동으로 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 (경로)를 사용하면 원하지 않는 상황이 발생할 수 있습니다. Paperclip은 File.new 인스턴스를 닫지 않으며 많은 첨부 파일을 처리 할 때 "너무 많은 파일 열기"와 같은 오류가 발생할 수 있습니다. 올바른 코드는 이어야합니다. f = File.new (로고 _ 경로) client.logo = f f.close' –

+2

아주 좋은 코멘트입니다. 적은 수의 파일로 아주 작은 작업을 수행 했으므로이 문제를 해결하지 못했습니다. 내 솔루션을 업데이트했습니다. 수동으로 닫기 대신 File.open 을 사용하는 것이 더 좋습니다. – kikito

11

Paperclip에 저장된 파일은 양식을 통해 직접 업로드 할 필요가 없습니다.

프로젝트에서 Paperclip을 사용하여 webcrawler 결과의 URL에서 파일을 저장합니다. 나는 당신이 이메일 첨부 파일을 어떻게 얻을 것인지 확신하지 못한다. (그것들은 서버의 로컬 파일 시스템에 있는가? 당신의 앱은 GMail과 같은 이메일 애플리케이션인가?) 그러나 파일 스트림을 얻을 수있는 한, open(URI.parse(crawl_result)) 내 경우 ...) has_attached_file이라고 표시된 모델 필드에 해당 파일을 첨부 할 수 있습니다.

블로그 게시물은 Easy Upload via URL with Paperclip입니다. 지금 원래 블로그 게시물을 보이므로

를 더 이상 사용할 수 없습니다 - 여기 뒤로 기계에서 뽑아 그것의 요점이다 :

이 예제는 이미지 첨부 파일이있는 사진의 모델을 보여준다는.

우리가 사용하는 기술은 원본 URL을 저장하는 데 사용되는 첨부 파일에 *_remote_url (문자열) 열을 추가해야합니다. 따라서이 경우 photos 테이블이라는 image_remote_url 열을 추가해야합니다. 사람들이 파일을 업로드하거나 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라는 추가하지
# 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

달콤한! 고마워요! –

+0

@ 네이트이 의견을 보내 주셔서 감사합니다. 링크가 더 이상 작동하지 않는 것 같습니다. –

+0

대용량 파일을 다운로드 할 때 꽤 많은 메모리가 필요합니다. 두 번째로, 10KB 미만의 파일에 대해 StringIO가 반환되고 클립 클립이 콘텐츠 형식 유효성 검사를 수행하는 경우 문자열에 콘텐츠 형식이 없으므로 실패합니다. – maletor

관련 문제