为什么OpenURI将10kb以下的文件视为StringIO?

时间:2012-05-08 10:30:14

标签: ruby standard-library

我使用open-uri从远程网站获取图像,并在Ruby on Rails应用程序中将它们保存在我的本地服务器上。大多数图像显示没有问题,但有些图像没有出现。

经过一段很长的调试会话后,我终于发现了(感谢this blogpost),原因是open-uri-libary中的class Buffer处理的文件少于10kb大小为IO对象而不是临时文件。

我设法绕过这个问题,按照Micah Winkelspecht的回答this StackOverflow question,我将以下代码放在初始化程序的文件中:

require 'open-uri'
# Don't allow downloaded files to be created as StringIO. Force a tempfile to be created.
OpenURI::Buffer.send :remove_const, 'StringMax' if OpenURI::Buffer.const_defined?('StringMax')
OpenURI::Buffer.const_set 'StringMax', 0

到目前为止,这可以按预期工作,但我一直在想,为什么他们首先将这些代码放入库中?有没有人知道具体原因,为什么10kb以下的文件被视为StringIO?

由于上面的代码实际上为我的整个应用程序全局重置了这种行为,我只是想确保我没有破坏任何其他内容。

1 个答案:

答案 0 :(得分:14)

当进行网络编程时,您可以分配一个相当大的缓冲区,并发送和读取适合缓冲区的数据单元。但是,在处理文件(或有时称为BLOB)时,您不能假设数据适合您的缓冲区。因此,您需要对这些大型数据流进行特殊处理。

(有时适合缓冲区的数据单位称为数据包。但是,数据包实际上是第4层,就像帧在第2层。由于这发生在第7层,它们最好被称为消息。 )

对于大于10K的回复,open-uri库正在设置写入流对象的额外开销。当在StringMax大小下时,它只包含消息中的字符串,因为它知道它可以放在缓冲区中。