2012-02-29 60 views
3

當試圖open()遠程圖像,一些返回爲StringIO和其他返回爲File ...我如何強制FileRuby打開返回字符串而不是文件?

data = open("http://graph.facebook.com/61700024/picture?type=square") 
=> #<StringIO:0x007fd09b013948> 

data = open("http://28.media.tumblr.com/avatar_7ef57cb42cb0_64.png") 
=> #<StringIO:0x007fd098bf9490> 

data = open("http://25.media.tumblr.com/avatar_279ec8ee3427_64.png") 
=> #<File:/var/folders/_z/bb18gdw52ns0x5r8z9f2ncj40000gn/T/open-uri20120229-9190-mn52fu> 

我使用回形針保存遠程圖像(其被存儲在S3),所以基本上想要做:

user = User.new 
user.avatar = open(url) 
user.save 
+0

的問題是:爲什麼你需要嗎?你想強制將這些圖像寫入臨時文件嗎?您可以輕鬆地自己做到這一點,並更好地控制它們的存儲位置和刪除時間。 – 2012-02-29 15:23:25

+0

@NiklasB。只是更新了一些附加信息的帖子。 – Shpigford 2012-02-29 15:30:39

+0

該代碼有什麼問題?它會給出任何錯誤嗎? Paperclip應該能夠處理任何類型的流,可能問題在於它無法找到圖像的基本名稱(通過向'StringIO'對象添加單例方法可以解決這個問題)。 – 2012-02-29 15:52:34

回答

12

Open-URIStringIO對象10KB限制,上述任何或它將其存儲爲臨時文件。

通過這種方法的一種方法是通過實際改變Open-URI用於限制StringIO對象的常量。您可以通過將常量設置爲0來完成此操作;

OpenURI::Buffer.send :remove_const, 'StringMax' if OpenURI::Buffer.const_defined?('StringMax') 
OpenURI::Buffer.const_set 'StringMax', 0 

添加到您的初始者,你應該很好去。

+1

呵呵,討厭的破解:) – 2012-02-29 15:24:30

+1

順便說一下,這會不必要地和全局地強制使用'uri-open'將任何代碼寫入文件的代碼。 – 2012-02-29 15:53:22

+0

@NiklasB。如果您在執行任何需要的操作後將'StringMax'重置爲10KB,則不是。不知道每次達到特定代碼塊時反覆取消/設置的開銷是多少,但有一個選項... – Dan 2014-07-06 19:29:44

0

雖然steigers解決方案是一種簡單的全方位解決方案,但我們中的一些人可能被它的「討厭的黑客」感覺和它在全球範圍內改變行爲的方式所排斥。包括其他可能會受益於OpenURI的這個特性的寶石。 OFC。你也可以使用上面的方法,然後當你完成將常量重置回它的原始值,並且因爲GIL你可能會帶着這種壞習慣(儘管一定要遠離jruby和線程!)。 。

或者你可以做這樣的事情,這基本上可以確保如果你得到它的管道輸送到一個臨時文件流:

def write_stream_to_a_temp_file(stream) 
    ext = begin 
    "."+MIME::Types[stream.meta["content-type"]].first.extensions.first 
    rescue #In case meta data is not available 
    #It seems sometimes the content-type is binary/octet-stream 
    #In this case we should grab the original ext name. 
    File.extname(stream.base_uri.path) 
    end 
    file = Tempfile.new ["temp", ext] 
    begin 
    file.binmode 
    file.write stream.read 
    ensure 
    file.flush rescue nil 
    file.close rescue nil 
    end 
    file 
end 

# and when you want to enforce that data must be a temp file then just... 
data = write_stream_to_a_temp_file data unless data.is_a? Tempfile 
相關問題