В чем разница между send_data и send_file в Ruby on Rails? - PullRequest
75 голосов
/ 04 апреля 2011

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

Пожалуйста, приведите примеры.

Ответы [ 2 ]

100 голосов
/ 04 апреля 2011
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 )
18 голосов

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

Как указано fl00r , 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

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

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

...