我有两张有效的网址到两张图片。 当我在第一个URL上运行open()时,它返回一个Tempfile类型的对象(这是fog gem希望将图像上传到AWS的对象)。 当我在第二个URL上运行open()时,它返回一个StringIO类型的对象(这会导致雾宝石崩溃并烧毁)。
为什么open()没有为第二个URL返回Tempfile? 此外,open()是否可以强制始终返回Tempfile?
从我的Rails控制台:
2.2.1 :011 > url1
=> "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xpf1/v/t1.0-1/c0.0.448.448/10298878_10103685138839040_6456490261359194847_n.jpg?oh=e2951e1a1b0a04fc2b9c0a0b0b191ebc&oe=56195EE3&__gda__=1443959086_417127efe9c89652ec44058c360ee6de"
2.2.1 :012 > url2
=> "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xfa1/v/t1.0-1/c0.17.200.200/1920047_10153890268465074_1858953512_n.jpg?oh=5f4cdf53d3e59b8ce4702618b3ac6ce3&oe=5610ADC5&__gda__=1444367255_396d6fdc0bdc158e4c2e3127e86878f9"
2.2.1 :013 > t1 = open(url1)
=> #<Tempfile:/var/folders/58/lpjz5b0n3yj44vn9bmbrv5180000gn/T/open-uri20150720-24696-1y0kvtd>
2.2.1 :014 > t2 = open(url2)
=> #<StringIO:0x007fba9c20ae78 @base_uri=#<URI::HTTPS https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xfa1/v/t1.0-1/c0.17.200.200/1920047_10153890268465074_1858953512_n.jpg?oh=5f4cdf53d3e59b8ce4702618b3ac6ce3&oe=5610ADC5&__gda__=1444367255_396d6fdc0bdc158e4c2e3127e86878f9>, @meta={"last-modified"=>"Tue, 25 Feb 2014 19:47:06 GMT", "content-type"=>"image/jpeg", "timing-allow-origin"=>"*", "access-control-allow-origin"=>"*", "content-length"=>"7564", "cache-control"=>"no-transform, max-age=1209600", "expires"=>"Mon, 03 Aug 2015 22:01:40 GMT", "date"=>"Mon, 20 Jul 2015 22:01:40 GMT", "connection"=>"keep-alive"}, @metas={"last-modified"=>["Tue, 25 Feb 2014 19:47:06 GMT"], "content-type"=>["image/jpeg"], "timing-allow-origin"=>["*"], "access-control-allow-origin"=>["*"], "content-length"=>["7564"], "cache-control"=>["no-transform, max-age=1209600"], "expires"=>["Mon, 03 Aug 2015 22:01:40 GMT"], "date"=>["Mon, 20 Jul 2015 22:01:40 GMT"], "connection"=>["keep-alive"]}, @status=["200", "OK"]>
这就是我使用雾的方式:
tempfile = open(params["avatar"])
user.avatar.store!(tempfile)
答案 0 :(得分:9)
我假设您使用的是Ruby的内置open-uri
库,可让您使用open()
下载网址。
在这种情况下,Ruby只有义务返回IO
个对象。无法保证它将是一个文件。我的猜测是Ruby根据内存消耗做出决定:如果下载很大,它会将其放入文件中以节省内存;否则它会使用StringIO
将其保存在内存中。
作为一种解决方法,您可以编写一个方法,将流写入临时文件(如果尚未下载到文件中):
def download_to_file(uri)
stream = open(uri, "rb")
return stream if stream.respond_to?(:path) # Already file-like
Tempfile.new.tap do |file|
file.binmode
IO.copy_stream(stream, file)
stream.close
file.rewind
end
end
如果您正在寻找功能相似的全功能宝石,请查看&#34; down&#34;:https://github.com/janko-m/down
答案 1 :(得分:3)
open uri库的大小限制为10K,可选择StringIO或Tempfile。
我的建议是更改为常量OpenURI::Buffer::StringMax
,用于打开uri设置默认值
在你的初始化程序中,你可以做到这一点:
require 'open-uri'
OpenURI::Buffer.send :remove_const, 'StringMax' if OpenURI::Buffer.const_defined?('StringMax')
OpenURI::Buffer.const_set 'StringMax', 0
答案 2 :(得分:0)
这并没有回答我的问题 - 但它提供了一个使用httparty gem的工作替代方案:
{{1}}