使用大小小于10kb的开放URI和回形针存储图像

我想从旧网站导入一些图标。 这些图标的大小小于10kb。 因此,当我尝试导入图标时,返回的stringio.txt文件。

require "open-uri" class Category  ":rails_root/public/:attachment/:id/:style/:basename.:extension" def icon_from_url(url) self.icon = open(url) end end 

在rake任务中。

  category = Category.new category.icon_from_url "http://sofzh.miximages.com/ruby-on-rails/" category.save 

尝试:

 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 

要覆盖Paperclip中的“假文件上传”的默认文件名(小文件上的stringio.txt或较大文件上几乎随机的临时名称),您有两种主要可能性:

在IO上定义original_filename

 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) 

或者在:path替换:basename

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

记得在更改:path icon.url更改:url ,否则icon.url方法会出错。

您还可以定义自己的自定义插值 (例如:rails_root/public/:whatever )。

我认为你几乎就在那里,尝试打开解析的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 

当然这不会处理错误

您还可以禁用OpenURI创建StringIO对象,并强制它创建临时文件。 看到这个SO答案:

为什么Ruby open-uri打开在我的unit testing中返回一个StringIO,但在我的控制器中是一个FileIO?

在过去,我发现检索远程文件的最可靠方法是使用命令行工具“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 

rake任务逻辑可能如下所示:

 [ ['Cat', 'cat'], ['Dog', 'dog'], ].each do |name, icon| CategoryIconImporter.import_from_url {:name => name}, "http://sofzh.miximages.com/ruby-on-rails/" end 

这使用mime-types gem进行内容类型发现:

 gem 'mime-types', :require => 'mime/types'