【问题标题】:Rails sends 0 byte files using send_fileRails 使用 send_file 发送 0 字节文件
【发布时间】:2011-04-13 02:19:18
【问题描述】:

我无法让 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 远程(RHEL5)到本地(Win7)然后本地(Win7)到远程(Ubuntu10)。

我知道 FTP 不会通过传输保留文件权限,所以我还模仿了我以前服务器上看到的 chmod,因此它们几乎相同。 (用户/组不同,设置为 root:root 而不是 olduser:olduser)。

从我的生产日志中下载附件的请求的 sn-p。

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

一切都好。让我也排除本地问题,我尝试在 Win7 和 Ubuntu(在 Vbox 上)上通过 Chrome 下载。

让我也向你保证,这条路确实是正确的。

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 字节垃圾。

【问题讨论】:

    标签: ruby-on-rails linux nginx


    【解决方案1】:

    send_file 具有 :x_sendfile 参数,在 Rails 3 中默认为 true。 此功能通过返回带有路径的 X-Sendfile 标头的空响应,将流式下载卸载到前端服务器 - Apache(使用 mod_xsendfile)或 lighttpd。

    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 中,只需在环境文件夹内的 production.rb 中取消注释 config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' 行。

    【讨论】:

      【解决方案3】:

      是的,在 Rails 3 中默认启用 X-sendfile 时我也遇到了同样的问题。

      如果您有大量的“send_file”调用, 您可以在 config/environments/production.rb 中注释掉以下行:

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

      然后send_file 方法开始完美运行。

      因为我无法安装 x-sendfile 扩展到 Apache,所以我只是搜索了一下,发现了这个。

      希望对你有帮助。

      【讨论】:

      • 在 apache 安装上,这也立即解决了我的问题。很好发现
      【解决方案4】:

      过去我在使用 send_file() 时遇到过类似的问题,当时使用 send_data() 代替了我(例如 send_data File.read(filename), :disposition => 'inline', :type => "some /mimetype")

      【讨论】:

      • 谢谢你,为我节省了大量的调试时间,因为我不想注释掉配置。
      【解决方案5】:

      在 Rails 4 上,我意识到我的问题是我删除了我生成的要发送给用户的临时文件。

      如果我没有删除文件,send_file 会起作用。我没有在 Thin 上进行测试,但它在作为独立服务器的旅客 5 上运行良好。

      【讨论】:

        猜你喜欢
        • 2011-06-18
        • 1970-01-01
        • 1970-01-01
        • 2017-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-13
        • 2015-09-04
        相关资源
        最近更新 更多