Поддержка двоичных потоков Rails

В ближайшее время я начну проект, который потребует поддержки двоичных файлов большого размера. Я хотел бы использовать Ruby on Rails для webapp, но я заинтересован в поддержке BLOB. В моем опыте работы с другими языками, фреймворками и базами данных BLOB часто пропускаются и, следовательно, имеют плохую, сложную и/или багги функциональность.

Соответствует ли RoR spport BLOB? Есть ли какие-либо ошибки, которые ползут, как только вы уже привязаны к Rails?

BTW: Я хочу использовать PostgreSQL и/или MySQL в качестве базы данных. Очевидно, что поддержка BLOB в базовой базе данных важна. На данный момент я хочу избежать фокусировки на возможностях DB BLOB; Меня больше интересует, как реагирует сам Rails. В идеале Rails должен скрывать детали базы данных от меня, и поэтому я должен иметь возможность переключаться с одного на другой. Если это не так (например, есть проблема с использованием Rails с конкретным БД), то, пожалуйста, упомяните об этом.

UPDATE: Кроме того, я говорю не только об ActiveRecord. Мне нужно обработать двоичные файлы на стороне HTTP (эффективно загружать файлы). Это означает получение доступа к соответствующим HTTP-заголовкам и потокам через Rails. Я обновил заголовок и описание вопроса, чтобы отразить это.

Ответы

Ответ 1

+1 для attachment_fu

Я использую attachment_fu в одном из моих приложений и ДОЛЖЕН хранить файлы в БД (по досадным причинам, выходящим за рамки этого конвоя).

(одна?) сложная вещь, связанная с BLOB, которую я обнаружил, заключается в том, что вам нужен отдельный путь кода для отправки данных пользователю - вы не можете просто вставить путь к файловой системе, как вы если бы это был простой файл Джейн.

например. если вы храните информацию об аватаре, вы не можете просто сделать:

<%= image_tag @youruser.avatar.path %>

вам нужно написать некоторую логику оболочки и использовать send_data, например. (ниже JUST пример w/attachment_fu, на практике вам нужно DRY это)

send_data(@youruser.avatar.current_data, :type => @youruser.avatar.content_type, :filename => @youruser.avatar.filename, :disposition => 'inline' )

К сожалению, насколько я знаю, attachment_fu (у меня нет последней версии) не делает для вас умной упаковки - вы должны написать ее самостоятельно.

P.S. Увидев ваш вопрос, редактируйте - Attachment_fu обрабатывает все, что раздражает, о чем вы упоминаете, - о необходимости знать пути к файлам и все это дерьмо - ЗА ИСКЛЮЧЕНИЕМ одной маленькой проблемы при хранении в БД. Попробуйте; это стандарт для приложений rails. Если вы настаиваете на повторном создании колеса, исходный код для attachment_fu должен также документировать большую часть gotchas!

Ответ 2

Что касается потоковой передачи, вы можете сделать все это в (по крайней мере, в памяти). На стороне загрузки параметры файла в формах абстрагируются как объекты ввода-вывода, которые вы можете прочитать; на стороне загрузки, посмотрите на форму render :text =>, которая принимает аргумент Proc:

render :content_type => 'application/octet-stream', :text => Proc.new {
    |response, output|
    # do something that reads data and writes it to output
}

Если ваши файлы находятся в файлах на диске, все же вышеупомянутые решения, безусловно, будут работать лучше.

Ответ 3

Вы можете использовать тип :binary в своей миграции ActiveRecord, а также ограничить максимальный размер:

class BlobTest < ActiveRecord::Migration
  def self.up
    create_table :files do |t|
      t.column :file_data, :binary, :limit => 1.megabyte
    end
  end
end

ActiveRecord предоставляет содержимое BLOB (или CLOB) как строку Ruby.

Ответ 5

Посмотрите плагин, x_send_file.

"Плагин XSendFile предоставляет простой интерфейс для отправки файлов через HTTP-заголовок X-Sendfile. Это позволяет вашему веб-серверу обслуживать файл непосредственно с диска, а не передавать его через ваш Rails-процесс. Это быстрее и экономит много памяти, если вы используете Mongrel. Не каждый веб-сервер поддерживает этот заголовок. YMMV."

Я не уверен, что он можно использовать с Blobs, это может быть только файл в файловой системе. Но вам, вероятно, нужно что-то, что не связывает веб-сервер с потоком больших фрагментов данных.