5

古いサイトからいくつかのアイコンをインポートしたいと思います。これらのアイコンのサイズは10kb未満です。したがって、アイコンをインポートしようとすると、返されるstringio.txtファイルが返されます。

require "open-uri"
class Category < ActiveRecord::Base
   has_attached_file :icon,  :path => ":rails_root/public/:attachment/:id/:style/:basename.:extension"
  def icon_from_url(url)
    self.icon = open(url)
   end    
end

レーキタスクで。

   category = Category.new
   category.icon_from_url "https://xyz.com/images/dog.png"
   category.save
4

5 に答える 5

36

試す:

def icon_from_url(url)
  extname = File.extname(url)
  basename = File.basename(url, extname)

  file = Tempfile.new([basename, extname])
  file.binmode

  open(URI.parse(url)) do |data|  
    file.write data.read
  end

  file.rewind

  self.icon = file
end
于 2011-06-12T22:12:04.017 に答える
9

Paperclipの「偽のファイルアップロード」のデフォルトのファイル名を上書きするには(stringio.txt小さなファイルの場合、または大きなファイルの場合はほぼランダムな一時的な名前)、2つの主な可能性があります。

original_filenameIOでを定義します。

def icon_from_url(url)
  io = open(url)
  io.original_filename = "foo.png"
  self.icon = io
end

URIからファイル名を取得することもできます。

io.original_filename = File.basename(URI.parse(url).path)

または、次のように置き換え:basenameます:path

has_attached_file :icon, :path => ":rails_root/public/:attachment/:id/:style/foo.png", :url => "/:attachment/:id/:style/foo.png"

:urlを変更するときは常に変更することを忘れないでください。:pathそうしないと、icon.url方法が間違ってしまいます。

独自のカスタム補間を定義することもできます(例:rails_root/public/:whatever)。

于 2011-06-13T07:48:41.830 に答える
1

文字列ではなく、解析されたURIを開いてみてください。

require "open-uri"
class Category < ActiveRecord::Base
   has_attached_file :icon,  :path =>:rails_root/public/:attachment/:id/:style/:basename.:extension"
  def icon_from_url(url)
    self.icon = open(URI.parse(url))
  end    
end

もちろん、これはエラーを処理しません

于 2011-06-12T21:55:02.810 に答える
1

OpenURIがStringIOオブジェクトを作成しないようにし、代わりに一時ファイルを作成するように強制することもできます。このSOの答えを参照してください:

Ruby open-uriのopenがユニットテストでStringIOを返すのに、コントローラーでFileIOを返すのはなぜですか?

于 2013-03-22T19:37:31.787 に答える
-2

以前は、リモートファイルを取得する最も信頼できる方法は、コマンドラインツール「wget」を使用することでした。次のコードは、ほとんどの場合、既存の本番(Rails 2.x)アプリから直接コピーされており、コード例に合わせていくつかの調整が加えられています。

class CategoryIconImporter
  def self.download_to_tempfile (url)
    system(wget_download_command_for(url))
    @@tempfile.path
  end

  def self.clear_tempfile
    @@tempfile.delete if @@tempfile && @@tempfile.path && File.exist?(@@tempfile.path)
    @@tempfile = nil
  end

  def self.set_wget
    # used for retrieval in NrlImage (and in future from other sies?)
    if !@@wget
      stdin, stdout, stderr = Open3.popen3('which wget')
      @@wget = stdout.gets
      @@wget ||= '/usr/local/bin/wget'
      @@wget.strip!
    end
  end
  def self.wget_download_command_for (url)
    set_wget
    @@tempfile = Tempfile.new url.sub(/\?.+$/, '').split(/[\/\\]/).last
    command = [ @@wget ]
    command << '-q'
    if url =~ /^https/
      command << '--secure-protocol=auto'
      command << '--no-check-certificate'
    end
    command << '-O'
    command << @@tempfile.path
    command << url
    command.join(' ')
  end

  def self.import_from_url (category_params, url)
    clear_tempfile

    filename = url.sub(/\?.+$/, '').split(/[\/\\]/).last
    found = MIME::Types.type_for(filename)
    content_type = !found.empty? ? found.first.content_type : nil

    download_to_tempfile url

    nicer_path = RAILS_ROOT + '/tmp/' + filename
    File.copy @@tempfile.path, nicer_path

    Category.create(category_params.merge({:icon => ActionController::TestUploadedFile.new(nicer_path, content_type, true)}))
  end
end

レーキタスクロジックは次のようになります。

[
  ['Cat', 'cat'],
  ['Dog', 'dog'],
].each do |name, icon|
  CategoryIconImporter.import_from_url {:name => name}, "https://xyz.com/images/#{icon}.png"
end

これは、コンテンツタイプの検出にmime-typesgemを使用します。

gem 'mime-types', :require => 'mime/types'
于 2011-06-15T02:25:20.817 に答える