Rails使用send_file发送0字节文件

时间:2010-09-16 08:15:55

标签: ruby-on-rails linux nginx

我无法使send_file(Model.attachment.path)工作。 它不会失败,相反,它会向客户端发送一个0字节大小的文件,但文件名是正确的。

在我从Rails 2.3.8迁移到3之后,这个问题就开始发生了。

此次迁移中还发生了很多其他事情,我会尽力详细说明所有这些内容。

  1. Distrubution change / Server Change。 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,但它没有用)。
  5. 我通过ftp移动了附件,因为它们不是我的git存储库的一部分,因此它们通过cap deploy发布,而不是手动ftp远程(RHEL5)到本地(Win7),然后是本地(Win7)到远程(Ubuntu10)。 / p>

    我知道FTPing不会通过传输保留文件权限,所以我所做的就是模仿我之前服务器上看到的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
    

    一切都没问题。我还要排除本地问题,我尝试在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字节垃圾。

5 个答案:

答案 0 :(得分:45)

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;

答案 1 :(得分:18)

在Rails 3中,只需在production.rb内部环境文件夹中取消注释 config.action_dispatch.x_sendfile_header ='X-Accel-Redirect'一行。

答案 2 :(得分:14)

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

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

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

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

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

我希望它有所帮助。

答案 3 :(得分:3)

我过去曾遇到类似send_file()的问题,使用send_data()而不是保存我(例如send_data File.read(filename),:disposition =>'inline',:type => “一些/ MIME类型”)

答案 4 :(得分:0)

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

如果我没有删除文件,send_file可以正常工作。 我没有测试过薄,但它在乘客5作为独立服务器上运行良好