少し前に自分で問題の少なくとも一部に遭遇した(そして解決した)ので、ここで問題を理解していると思います。
私はいくつかの大きなmp3を持っていて、私のWebサイトでそれらにリンクしています
いくつかの問題
- ユーザーがダウンロードボタンをクリックするたびにファイルが自動的にストリーミングされないようにするには、 content-dispositionヘッダーを添付ファイルに設定する必要がありました。
- 私のファイルはリモートサーバー上にあります
- 私のファイルは大きい(100MB)
- 大きなファイルは、適切に処理されない場合、レールコントローラを拘束する可能性があります
さて、Michael Koziarskyはこの記事で、大きなファイルを提供するときにRailsプロセスを解放する最善の方法は、コントローラーでダウンロードアクションを作成し、次のようにすることであるとアドバイスしています( x_sendfile => trueの使用に注意してください)。
def download
send_file '/path/to/podcast.mp3', :type => 'application/octet-stream', :disposition => 'attachment', :filename=>'something.mp3', :x_sendfile=>true
end
:x_sendfileは、Railsコントローラープロセスを拘束せずにファイルを通過させるようにapacheに指示します。コードの残りの部分は、ファイル名とcontent-dispositionヘッダーを設定します。
すばらしいですが、最近は他のみんなと同じように、私はherokuを使用しています。そのため、x_sendfileを使用できません。
nginx構成ファイルがherokuによってロックダウンされているため、変更できないことがわかりました。そのため、x-accel-redirect ( x-sendfileと同等のnginx)を機能させることができませんでした。
そこで、アセットホストのcgi-binにperlスクリプト(以下を参照)を追加することにしました。このスクリプトは、content-dispositionを添付ファイルに設定し、ファイルにも名前を付けます。
このような安らかなダウンロードを行う代わりに:
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スクリプトを見つけ、それを少し切り刻んで私のために機能させました:
#!/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変数を多用しており、ドキュメントやテストがないため、マシンで使用するとさまざまな問題が発生する可能性があります^ hidden ^