2012-02-29 19 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 
相关问题