В чем разница между send_data и send_file в Ruby on Rails?
Какой из них лучше всего подходит для потоковой передачи и загрузки файлов?
Пожалуйста, приведите примеры.
2 ответа
send_data(_data_, options = {})
send_file(_path_, options = {})
Основное отличие состоит в том, что вы передаете DATA (двоичный код или что-то еще) с 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 )
send_file может быть быстрее send_data
Как уже упоминалось, send_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 появится возможность принять решение. Это обсуждается в разделе: Защита содержимого public / в приложении Rails
Для того, чтобы использовать X-Sendfile
Заголовки, вы должны добавить:
config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
в confing/initializers/production.rb
(не application.rb
, так как в разработке у вас нет прокси-сервера, и вы хотите send_file
на самом деле отправить данные).
X-Sendfile
обсуждается в Руководстве по конвейеру активов.