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

kla*_*eck 22 ruby standard-library

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

一个很长的调试会话后,我终于找到了(感谢我这篇文章),对于这种情况的原因是,class Buffer开放的URI libary对待与文件大小小于作为IO对象,而不是临时文件10KB.

我设法通过Micah Winkelspecht对这个StackOverflow问题的回答解决了这个问题,我将以下代码放在我的初始化器中的文件中:

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
Run Code Online (Sandbox Code Playgroud)

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

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

Mar*_*rce 14

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

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

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

  • 不太正确.在这种情况下用作缓冲区的字符串没有固定大小; Ruby中的字符串是动态调整大小的.实际上,您可以在大多数语言中动态调整缓冲区大小(尽管并非总是自动调整).我怀疑将StringIO用于小文件的真正原因是性能/内存使用权衡. (3认同)
  • 真正的@pelle.注意到你说不太完整.在BLOB的情况下,*任何关于拟合的假设都可以被更大的BLOB打破.这包括不适合记忆的内容.在某些时候,处理流需要流式传输,而Buffer类正在选择10K作为临界点,以便通过流式传输放弃和处理文件. (3认同)