Rails отправляет 0-байтовые файлы, используя send_file - PullRequest
23 голосов
/ 16 сентября 2010

Я не могу заставить send_file (Model.attachment.path) работать. Он не дает сбоя, вместо этого он отправляет клиенту файл размером 0 байт, хотя имена файлов правильные.

Эта проблема начала возникать после большого перехода с Rails 2.3.8 на 3.

В ходе этой миграции произошло много других вещей, и я постараюсь описать их все.

  1. Смена дистрибуции / Смена сервера. Rackspace RHEL5 для Linode Ubuntu 10.04LTS
  2. Изменение версии Ruby, 1.8.6 -> 1.9.2
  3. Изменение версии Rails, 2.3.8 -> 3.0.0
  4. Смена платформы httpd, apache2 -> nginx (Тем не менее, я попробовал и на apache2, но это не сработало).

Я переместил вложения через ftp, так как они не были частью моего git-репозитория, поэтому они были опубликованы через cap deploy, вместо этого вручную ftp remote (RHEL5) на локальный (Win7), затем локальный (Win7) на удаленный (Ubuntu10).

Я знаю, что FTP не сохраняет права доступа к файлам при передаче, поэтому я также сделал имитацию chmod, которые были на моих предыдущих серверах, поэтому они почти идентичны. (пользователи / группы различны, для пользователя установлено значение 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).

Позвольте мне также заверить вас, что путь действительно правильный.

root@li162-41:/srv/app/current# tail /srv/app/releases/20100916094249/attachments/replies/UE0003-Requisition_For_Compensation_Leave.doc
#
    #
         %17nw
                 HQ��+1ae����
                                             %33333333333(��QR���HX�"%%��@9
��@�p4��#P@��Unknown������������G��z �Times New Roman5��Symbol3&�
                       �z �Arial5&�

Итак, чтобы подвести итог вопроса, как получить send_file для фактической отправки файлов вместо поддельного 0-байтового мусора.

Ответы [ 5 ]

45 голосов
/ 16 сентября 2010

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;
18 голосов
/ 02 декабря 2010

В Rails 3 просто раскомментируйте строку config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' в production.rb внутри папки окружения.

14 голосов
/ 17 декабря 2010

Да, у меня была такая же проблема с X-sendfile, который по умолчанию был включен в Rails 3.

Если у вас большой объем вызовов send_file, Вы можете просто закомментировать следующую строку в config / environment / production.rb:

#config.action_dispatch.x_sendfile_header = "X-Sendfile"

Тогда send_file метод начал работать отлично.

Поскольку я не могу установить расширение x-sendfile для Apache, я просто немного искал и нашел это.

Надеюсь, это поможет.

3 голосов
/ 03 декабря 2010

У меня были подобные проблемы с send_file () в прошлом, использование send_data () вместо этого спасло меня тогда (например, send_data File.read (filename),: disposition => 'inline',: type => "some/ MimeType ")

0 голосов
/ 02 августа 2015

на рельсах 4, я понимаю, что моя проблема в том, что я удалил временный файл, который я сгенерировал для отправки пользователю.

, если я не удалил файл, send_file работает.Я не тестировался на тонких, но отлично работает на пассажире 5 в качестве автономного сервера

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...