2015-07-20 18 views
0

我有兩個有效的URL的兩個圖像。 當我在第一個URL運行Open(),它返回一個類型將它視爲的對象(這就是霧寶石預計圖片上傳到AWS)。 當我在第二URL運行Open(),它返回StringIO的類型的對象(這會導致霧寶石玉石俱焚)。Rails的:open()返回StringIO的,而不是將它視爲

爲什麼是開放的()不返回將它視爲第二個網址是什麼? 此外,可以打開()強制總是返回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

這不回答我的問題 - 但它使用httparty創業板提供了一個可供選擇的工作:

require "httparty" 

File.open("file.jpg", "wb") do |tempfile| 
    tempfile.write HTTParty.get(params["avatar"]).parsed_response 
    user.avatar.store!(tempfile) 
end 
8

我假設你使用的是Ruby的內置open-uri庫,它允許你使用open()下載網址。

在這種情況下紅寶石僅有義務返回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 

如果你正在尋找一個全功能的寶石,做類似的東西,看看「下」:https://github.com/janko-m/down

+0

TNX!我在答案中做了類似的事情(但更簡單)。 – etayluz

+0

因此,在處理類似問題時,我發現'file.close'應該是'stream.close',並且在返回文件之前,首先應該使用'file.rewind'。沒有編輯你的答案,因爲我的紅寶石還是相當低劣的;) – sg3s

+0

@ sg3s偉大的建議,謝謝!我更新了我的答案。 –

0

開放的URI庫有10K大小限制選擇使用StringIO的或臨時文件。

我對你的建議是變化不斷的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 
相關問題