Rails отправляет 0 байтовые файлы с помощью send_file
Я не могу заставить send_file (Model.attachment.path) работать.
Он не терпит неудачу, вместо этого он отправляет клиенту файл размера 0 байтов, однако имена файлов верны.
Эта проблема возникла после большой миграции из Rails 2.3.8 в 3.
В этой миграции было много других вещей, и я попытаюсь изо всех сил детализировать их все.
- Изменение предложения/Изменение сервера. Rackspace RHEL5 - Linode Ubuntu 10.04LTS
- Изменение версии Ruby, 1.8.6 → 1.9.2
- Изменение версии Rails, 2.3.8 → 3.0.0
- Изменение платформы httpd, apache2 → nginx (Однако я также пробовал на apache2, и это не сработало).
Я переместил вложения через ftp, поскольку они не были частью моих репозиториев git, поэтому они были опубликованы с помощью командной оболочки, а вместо этого ручной ftp remote (RHEL5) на локальный (Win7), а затем локальный (Win7) на удаленный (Ubuntu10).
Я знаю, что FTP-передача не сохраняет права доступа к файлам через передачи, поэтому то, что я также сделал, имитирует chmods, которые были замечены на моих предыдущих серверах, поэтому они почти идентичны. (пользователи/группы разные, установите для root: root вместо olduser: olduser).
Отрывок запроса на загрузку вложения из моего журнала производства.
Started GET "/attachments/replies/1410?1277105698" for 218.102.140.205 at 2010-09-16 09:44:31 +0000
Processing by AttachmentsController#replies as HTML
Parameters: {"1277105698"=>nil, "id"=>"1410"}
Sent file /srv/app/releases/20100916094249/attachments/replies/UE0003-Requisition_For_Compensation_Leave.doc (0.2ms)
Completed 200 OK in 78ms
Все в порядке. Позвольте мне также исключить локальные проблемы, я попытался загрузить через Chrome на Win7 и Ubuntu (на Vbox).
Позвольте мне также заверить вас, что путь действительно правильный.
[email protected]:/srv/app/current# tail /srv/app/releases/20100916094249/attachments/replies/UE0003-Requisition_For_Compensation_Leave.doc
#
#
%17nw
HQ��+1ae����
%33333333333(��QR���HX�"%%��@9
��@�p4��#[email protected]��Unknown������������G��z �Times New Roman5��Symbol3&�
�z �Arial5&�
Итак, чтобы подвести итог, как мне получить send_file для фактической отправки файлов вместо поддельного байт-бана.
Ответы
Ответ 1
send_file
имеет параметр :x_sendfile
, который по умолчанию равен true
в Rails 3.
Эта функция выгружает потоковое скачивание на передний сервер - Apache (с mod_xsendfile) или lighttpd, возвращая пустой ответ с заголовком X-Sendfile с контуром.
Nginx использует заголовок X-Accel-Redirect
для той же функциональности, но вы должны
правильно настройте Rails в соответствующем файле среды:
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
Обновление Rails 3: эта строка уже существует в production.rb
, просто раскомментируйте ее.
Добавьте sendfile on;
в конфигурацию nginx, чтобы использовать заголовок, отправленный Rails.
Помните, что должен использоваться абсолютный путь, и nginx должен иметь доступ для чтения к файлу.
Другой способ для псевдонимов:
Для лучшей безопасности я использую псевдонимы в nginx вместо абсолютных путей,
однако метод send_file
проверяет существование файла с ошибкой с псевдонимом.
Таким образом, я изменил свое действие на:
head(
'X-Accel-Redirect'=> file_item.location,
'Content-Type' => file_item.content_type,
'Content-Disposition' => "attachment; filename=\"#{file_item.name}\"");
render :nothing => true;
Ответ 2
В Rails 3 просто раскомментируйте строку config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' в production.rb
внутри окружения.
Ответ 3
Да, у меня была такая же проблема, когда X-sendfile включен по умолчанию в Rails 3.
Если у вас большой объем вызовов "send_file",
вы можете просто прокомментировать следующую строку в config/environment/production.rb:
#config.action_dispatch.x_sendfile_header = "X-Sendfile"
Затем метод send_file
начал работать отлично.
Поскольку я не могу установить расширение x-sendfile для Apache, я просто немного искал и нашел это.
Надеюсь, это поможет.
Ответ 4
У меня были аналогичные проблемы с send_file() в прошлом, вместо этого вместо этого я заменил send_data() (например, send_data File.read(filename),: disposition = > 'inline',: type = > "some/MimeType" )
Ответ 5
на рельсах 4,
Я понимаю, что проблема заключается в том, что я удалил временный файл, который был создан для отправки пользователю.
Если я не удалял файл, send_file работает.
ive не тестируется на тонком, но отлично работает на пассажире 5 как автономный сервер