Почему OpenURI рассматривает файлы размером менее 10 КБ как StringIO?

Я получаю изображения с open-uri с удаленного веб-сайта и сохраняю их на моем локальном сервере в моем приложении Ruby on Rails. Большинство изображений было показано без проблем, но некоторые изображения просто не отображались.

После очень долгой сессии отладки я наконец-то узнал (спасибоэтот пост) что причина в том, чтоclass Buffer воткрытой Ури libary обрабатывает файлы размером менее 10 КБ как объекты ввода-вывода вместо временных файлов.

Мне удалось обойти эту проблему, следуя ответу Мики Винкельспехта наэтот вопрос StackOverflowгде я помещаю следующий код в файл в моих инициализаторах:

<code>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
</code>

Пока это работает, как и ожидалось, но я продолжаю задаваться вопросом, почему они поместили этот код в библиотеку в первую очередь? Кто-нибудь знает конкретную причину,why files under 10kb in size get treated as StringIO ?

Поскольку приведенный выше код практически сбрасывает это поведение глобально для всего моего приложения, я просто хочу убедиться, что я не нарушаю ничего другого.

Ответы на вопрос(1)

Решение Вопроса

вы выделяете буфер достаточно большого размера и отправляете и считываете единицы данных, которые помещаются в буфер. Однако при работе с файлами (или иногда с объектами, называемыми BLOB) вы не можете предполагать, что данные будут помещаться в ваш буфер. Итак, вам нужна специальная обработка для этих больших потоков данных.

(Иногда единицы данных, которые помещаются в буфер, называются пакетами. Однако пакеты на самом деле являются уровнем 4, например, кадры на уровне 2. Поскольку это происходит на уровне 7, их лучше называть сообщениями.)

Для ответов размером более 10 КБ библиотека open-uri устанавливает дополнительные издержки для записи в объекты потока. Когда размер меньше StringMax, он просто включает строку в сообщение, так как знает, что может поместиться в буфере.

 klaffenboeck08 мая 2012 г., 13:22
спасибо, хорошее объяснение
 13 янв. 2014 г., 09:42
Не совсем правильно. Строка, которая используется в качестве буфера в этом случае, не имеет фиксированного размера; строки в Ruby динамически изменяются. Действительно, вы можете динамически изменять размер буферов в большинстве языков (хотя не всегда автоматически). Я подозреваю, что настоящей причиной использования StringIO для небольших файлов является компромисс между производительностью и использованием памяти.
 31 янв. 2014 г., 17:13
Истинный @pelle. Отмечу, что ты сказал не совсем. В случае с BLOB,any предположение о примерке может быть нарушено еще большим BLOB. Это включает в себя то, что не помещается в память. В какой-то момент обработка потоков требует потоковой передачи, и класс Buffer выбирает 10K в качестве переломного момента, чтобы просто сдаться и обработать файл потоковой передачей.

Ваш ответ на вопрос