我想我理解这里的问题,因为不久前我自己遇到(并解决了)至少部分问题。
我有一些大的mp3's,我在我的website 上链接到它们
几个问题
- 我需要将我的 content-disposition 标头设置为 attachment 以防止文件在用户单击下载按钮时自动流式传输
- 我的文件在远程服务器上
- 我的文件很大 (100MB)
- 如果处理不当,大文件会占用 Rails 控制器
现在,Michael Koziarsky 在this article 中建议,在提供大文件时保持 Rails 进程免费的最佳方法是在控制器中创建下载操作,然后执行类似的操作(注意使用 x_sendfile=>真):
def download
send_file '/path/to/podcast.mp3', :type => 'application/octet-stream', :disposition => 'attachment', :filename=>'something.mp3', :x_sendfile=>true
end
:x_sendfile 告诉 apache 让文件通过而不占用 Rails 控制器进程。其余代码设置文件名和内容处置标头。
很好,但我在 heroku 上,现在和其他人一样。所以我不能使用 x_sendfile。
我发现我无法修改 nginx 配置文件,因为它被 heroku 锁定,所以无法获取 x-accel-redirect(nginx 相当于 x-发送文件)工作
所以,我决定在资产主机上的 cgi-bin 中添加一个perl script(见下文),此脚本将内容配置设置为 附件 并为我们的文件命名也是。
而不是像这样进行安静的下载:
link_to "download", download_podcast_path(@podcast.mp3)
我们只是链接到 mp3,确保我们通过 cgi-bin 进入,以便在离开服务器的每个 mp3 上调用 perl 脚本
# I'm using haml
%a{:href=>"http://afmpodcast.com/cgi-bin/download.cgi?ID=#{@podcast.mp3}"}
download
结果是当有人下载文件时,我的 rails 控制器不再被调用
我找到了 perl 脚本 here 并将其切碎以供我使用:
#!/usr/local/bin/perl -wT
use CGI ':standard';
use CGI::Carp qw(fatalsToBrowser);
my $files_location;
my $ID;
my @fileholder;
$files_location = "../";
$ID = param('ID');
open(DLFILE, "<$files_location/$ID") || Error('open', 'file');
@fileholder = <DLFILE>;
close (DLFILE) || Error ('close', 'file');
print "Content-Type:application/x-download\n";
print "Content-Disposition:attachment;filename=$ID\n\n";
print @fileholder
我的代码在github 上,但你可能会在你的机器上使用它时遇到各种问题,因为我大量使用了我存储在 bashrc 中的 ENV 变量并且我没有文档或测试 ^hides^