Почему OpenURI обрабатывает файлы размером менее 10 КБ как StringIO?
Я извлекаю изображения с открытым uri с удаленного сайта и сохраняю их на своем локальном сервере в моем приложении Ruby on Rails. Большинство изображений были показаны без проблем, но некоторые изображения просто не отображались.
После очень долгого отладочного сеанса я наконец узнал (спасибо этот блогпост), что причина этого в том, что class Buffer
в open-uri-libary обрабатывает файлы размером менее 10 КБ в качестве IO-объектов вместо tempfiles.
Мне удалось обойти эту проблему, выполнив ответ от Micah Winkelspecht на qaru.site/info/212624/..., где я поместил следующий код внутри файла в мои инициализаторы:
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?
Так как приведенный выше код практически полностью сбрасывает это поведение для всего моего приложения, я просто хочу убедиться, что я ничего не нарушаю.
Ответы
Ответ 1
Когда вы выполняете сетевое программирование, вы выделяете буфер с достаточно большим размером и отправляете и читаете единицы данных, которые будут помещаться в буфер. Однако при работе с файлами (или иногда вещами, называемыми BLOB) вы не можете предположить, что данные будут вписываться в ваш буфер. Итак, вам нужна специальная обработка для этих больших потоков данных.
(Иногда единицы данных, которые вписываются в буфер, называются пакетами. Однако пакеты действительно представляют собой уровень 4, например, кадры находятся на уровне 2. Поскольку это происходит с уровнем 7, их лучше назвать сообщениями. )
Для ответов, больших 10K, библиотека open-uri настраивает дополнительные служебные данные для записи в объекты потока. Когда в размере StringMax он просто содержит строку в сообщении, поскольку он знает, что он может поместиться в буфер.