В чем разница между send_data и send_file в Ruby on Rails?

79

Какой из них лучше всего подходит для потоковой передачи и загрузки файлов?

Приведите примеры.

Мистер Блэк
источник

Ответы:

109
send_data(_data_, options = {})
send_file(_path_, options = {}) 

Основное отличие здесь в том, что вы передаете ДАННЫЕ (двоичный код или что-то еще) с помощью send_data или PATH с помощью send_file .

Таким образом, вы можете сгенерировать некоторые данные и отправить их в виде встроенного текста или вложения, не создавая файл на своем сервере через send_data . Или вы можете отправить готовый файл с помощью send_file

data = "Hello World!"
send_data( data, :filename => "my_file.txt" )

Или же

data = "Hello World!"
file = "my_file.txt"
File.open(file, "w"){ |f| f << data }
send_file( file )

Для производительности лучше один раз сгенерировать файл, а затем отправлять его столько раз, сколько захотите. Так send_fileподойдет лучше.

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

UPD

send_data и сохраните файл:

data = "Hello World!"
file = "my_file.txt"
File.open(file, "w"){ |f| f << data }
send_data( data )
fl00r
источник
1
спасибо @ fl00r. Есть ли способ сохранить данные в виде файла, а затем отправить их с помощью функции send_data ?. Потому что мне нужна была копия файла на моем сервере. Как я могу этого добиться ?.
Мистер Блэк
В вашем коде есть ошибка: так и должно быть { |f| f << data }.
True Soft
Привет, мне интересно, актуален ли этот ответ? Сейчас я использую Rails 3.2.16, и send_fileмне пришлось использовать сам файл, а не путь, чтобы заставить его работать. Просто хотели обновить, если другие столкнутся с этим?
FireDragon
20

send_file может быть быстрее send_data

Как уже упоминалось , fl00rsend_file принимает путь и send_dataданные.

Следовательно send_file, это подмножество send_data, поскольку вам нужен файл в файловой системе: вы, конечно, можете просто прочитать файл и использовать send_dataего. Но send_fileможет быть и быстрее, так что это компромисс между производительностью и общностью.

send_fileможет быть быстрее, потому что он может отправлять X-Sendfileзаголовок в Apache ( X-Accel-Redirectна Nginx) вместо содержимого файла, поскольку он знает путь.

Этот заголовок используется обратным прокси (Apache или Nginx), который обычно запускается перед Rails в производственной установке.

Если X-Sendfileв ответе присутствует, обратный прокси-сервер игнорирует большую часть текущего ответа и создает новый, который возвращает файл по заданному пути.

Client <---> Internet <---> Reverse proxy <---> Rails

Это намного эффективнее, поскольку обратный прокси-сервер сильно специализируется на обслуживании статических файлов и может делать это намного быстрее, чем Rails (который не отправляет данные файла, если X-Sendfileони будут отправлены).

Типичный вариант использования send_file- это когда вы хотите контролировать права доступа к статическим файлам: вы не можете поместить их, /publicиначе они будут обработаны до того, как Rails сможет принять решение. Это обсуждается в: Защита содержимого публичного / в приложении Rails

Чтобы использовать X-Sendfileзаголовки, вам необходимо добавить:

config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx

к config/initializers/production.rb(или config/environment/production.rbв Rails 5.x), нет application.rb , поскольку в процессе разработки у вас нет прокси-сервера, и вы send_fileдействительно хотите отправлять данные.

X-Sendfileобсуждается в Руководстве по конвейеру активов .

Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
источник