Подтвердить что ты не робот

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 для фактической отправки файлов вместо поддельного байт-бана.

4b9b3361

Ответ 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 как автономный сервер