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
обсуждается в Руководстве по конвейеру активов .