2012-05-08 2 views
19

Я извлекаю изображения с открытым uri с удаленного сайта и сохраняю их на своем локальном сервере в моем приложении Ruby on Rails. Большинство изображений были показаны без проблем, но некоторые изображения просто не отображались.Почему OpenURI обрабатывает файлы размером до 10 КБ в качестве StringIO?

После очень долгой отладки-сессии я, наконец, узнал (благодаря this blogpost), что причина этого заключается в том, что class Buffer в open-uri-libary лечит файлы с менее чем 10kb размера, как IO-объектов вместо временных файлов.

мне удалось обойти эту проблему, после ответа от Михея 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 

Это работает, как ожидалось до сих пор, но я неужели интересно, почему они ввели этот код в библиотеку в первую очередь? Кто-нибудь знает определенную причину: Почему файлы размером менее 10 КБ рассматриваются как StringIO?

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

ответ

12

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

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

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

+0

спасибо, приятное объяснение – klaffenboeck

+3

Не совсем правильно. Строка, которая используется в качестве буфера в этом случае, не имеет фиксированного размера; строки в Ruby динамически изменяются. Действительно, вы можете динамически изменять размер буферов на большинстве языков (хотя не всегда автоматически). Я подозреваю, что реальной причиной использования StringIO для небольших файлов является компромисс между производительностью и памятью. – pelle

+2

True @pelle. Отмечая, что вы сказали не совсем. В случае BLOBs * любое * предположение об установке может быть разбито еще большим BLOB. Это включает в себя то, что не поместится в памяти. В какой-то момент обработка потоков требует потоковой передачи, а класс Buffer выбирает 10K в качестве точки опроса, чтобы просто сдаться и обработать файл потоком. –

 Смежные вопросы

  • Нет связанных вопросов^_^