Rails使用send_file发送0字节文件

时间:2023-02-06 00:19:42

I can't get send_file(Model.attachment.path) to work. It doesn't fail, instead, it sends a 0 byte size file to the client, the file names are correct though.

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

This problem started happening after I did a big migration from Rails 2.3.8 to 3.

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

There were a lot of other things that took place in this migration and I will try my best to detail all of them.

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

  1. Distrubution change/Server Change. Rackspace RHEL5 to Linode Ubuntu 10.04LTS
  2. Distrubution更改/服务器更改。 Rackspace RHEL5到Linode Ubuntu 10.04LTS
  3. Ruby version change, 1.8.6 -> 1.9.2
  4. Ruby版本更改,1.8.6 - > 1.9.2
  5. Rails version change, 2.3.8 -> 3.0.0
  6. Rails版本更改,2.3.8 - > 3.0.0
  7. httpd platform change, apache2 -> nginx (However I tried on apache2 as well and it did not work).
  8. httpd平台更改,apache2 - > nginx(不过我试过apache2也没用)。

I moved the attachments via ftp as they were not part of my git repositories so they were published via cap deploy, instead manual ftp remote(RHEL5) to local(Win7) then local(Win7) to remote(Ubuntu10).

我通过ftp移动附件,因为它们不是我的git存储库的一部分,因此它们通过cap deploy发布,而不是手动ftp远程(RHEL5)到本地(Win7)然后本地(Win7)到远程(Ubuntu10)。

I do know that FTPing does not retain the file permissions through the transfers, so what I've also done is mimicked the chmods that were seen on my previous servers so they are almost identical. (users/groups are different, set to root:root instead of olduser:olduser).

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

A snippet of the request to download a attachment from my production log.

从我的生产日志下载附件的请求的片段。

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

Everything's okay. Let me also rule out local issues, I've tried downloading via Chrome on both Win7 and Ubuntu (on Vbox).

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

Let me also assure you that the path is indeed correct.

我还要向你保证,这条道路确实是正确的。

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&�

So to sum up the question, how do I get send_file to actually send files instead of fake 0 byte junk.

总结一下这个问题,我如何让send_file实际发送文件而不是假的0字节垃圾。

5 个解决方案

#1


45  

send_file has :x_sendfile param which defaults to true in Rails 3. This feature offloads streaming download to front server - Apache (with mod_xsendfile) or lighttpd, by returning empty response with X-Sendfile header with path.

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

Nginx uses X-Accel-Redirect header for same functionality but you have to configure Rails properly in proper environment file:

Nginx使用X-Accel-Redirect标头来实现相同的功能,但您必须在适当的环境文件中正确配置Rails:

config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'

Rails 3 update: this line already exists in production.rb, just uncomment it.

Rails 3更新:此行已经存在于production.rb中,只需取消注释即可。

Add sendfile on; to your nginx config to utilize header sent by Rails. Remember the absolute path must be used and nginx must have read access to file.

添加sendfile;到您的nginx配置,以利用Rails发送的标头。请记住,必须使用绝对路径,并且nginx必须具有对文件的读访问权限。

Another way for aliased files:

别名文件的另一种方法:

For better security I use aliases in nginx instead of absolute paths, however send_file method checks existence of file which fails with alias. Thus I changed my action to:

为了更好的安全性,我在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


18  

In Rails 3, just uncomment the line config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' in production.rb inside environments folder.

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

#3


14  

Yes, I had the same problem with X-sendfile being enabled by default in Rails 3 too.

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

If you have large volume of "send_file" calls, you can just comment-out following line in config/environments/production.rb:

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

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

Then send_file method started working perfectly.

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

Because I can't install x-sendfile extension to Apache, I just searched a little and found this.

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

I hope it helps.

我希望它有所帮助。

#4


3  

I've had similar issues with send_file() in the past, using send_data() instead saved me back then (e.g. send_data File.read(filename), :disposition => 'inline', :type => "some/mimetype")

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

#5


0  

on rails 4, i realize my problem is that i deleted the temporary file which ive generated to send to user.

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

if i didnt delete the file, send_file works. ive not tested on thin but it works great on passenger 5 as standalone server

如果我没有删除该文件,send_file工作。我没有在瘦身上测试,但它在乘客5作为独立服务器上工作得很好

#1


45  

send_file has :x_sendfile param which defaults to true in Rails 3. This feature offloads streaming download to front server - Apache (with mod_xsendfile) or lighttpd, by returning empty response with X-Sendfile header with path.

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

Nginx uses X-Accel-Redirect header for same functionality but you have to configure Rails properly in proper environment file:

Nginx使用X-Accel-Redirect标头来实现相同的功能,但您必须在适当的环境文件中正确配置Rails:

config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'

Rails 3 update: this line already exists in production.rb, just uncomment it.

Rails 3更新:此行已经存在于production.rb中,只需取消注释即可。

Add sendfile on; to your nginx config to utilize header sent by Rails. Remember the absolute path must be used and nginx must have read access to file.

添加sendfile;到您的nginx配置,以利用Rails发送的标头。请记住,必须使用绝对路径,并且nginx必须具有对文件的读访问权限。

Another way for aliased files:

别名文件的另一种方法:

For better security I use aliases in nginx instead of absolute paths, however send_file method checks existence of file which fails with alias. Thus I changed my action to:

为了更好的安全性,我在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


18  

In Rails 3, just uncomment the line config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' in production.rb inside environments folder.

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

#3


14  

Yes, I had the same problem with X-sendfile being enabled by default in Rails 3 too.

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

If you have large volume of "send_file" calls, you can just comment-out following line in config/environments/production.rb:

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

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

Then send_file method started working perfectly.

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

Because I can't install x-sendfile extension to Apache, I just searched a little and found this.

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

I hope it helps.

我希望它有所帮助。

#4


3  

I've had similar issues with send_file() in the past, using send_data() instead saved me back then (e.g. send_data File.read(filename), :disposition => 'inline', :type => "some/mimetype")

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

#5


0  

on rails 4, i realize my problem is that i deleted the temporary file which ive generated to send to user.

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

if i didnt delete the file, send_file works. ive not tested on thin but it works great on passenger 5 as standalone server

如果我没有删除该文件,send_file工作。我没有在瘦身上测试,但它在乘客5作为独立服务器上工作得很好