我想从旧网站导入一些图标。这些图标的大小小于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
在rake任务中。
category = Category.new
category.icon_from_url "https://xyz.com/images/dog.png"
category.save
答案 0 :(得分:35)
尝试:
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
答案 1 :(得分:9)
要覆盖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)
或替换: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
方法将出错。
您还可以定义自己的custom interpolations(例如:rails_root/public/:whatever
)。
答案 2 :(得分: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
当然这不会处理错误
答案 3 :(得分:1)
您也可以禁用OpenURI创建StringIO对象,并强制它创建临时文件。看到这个答案:
Why does Ruby open-uri's open return a StringIO in my unit test, but a FileIO in my controller?
答案 4 :(得分:-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
rake任务逻辑可能如下所示:
[
['Cat', 'cat'],
['Dog', 'dog'],
].each do |name, icon|
CategoryIconImporter.import_from_url {:name => name}, "https://xyz.com/images/#{icon}.png"
end
这使用mime-types gem进行内容类型发现:
gem 'mime-types', :require => 'mime/types'