Nginx で認証つきで大容量ファイルをダウンロードさせたい時は、X-Accel-Redirect を使います。Rails のファイル操作を介さず、Nginxで直接クライアントへデータを送れます。Lighttpd とか Apache でいうところの、X-sendfile と同じような感じでしょうか。
Lighttpd の場合はこちら -> Rails&Lighttpdで大容量ファイルをダウンロード【変なヤバいもんログ内】
ヘッダに、X-Accel-Redirect でパスを指定して、そのパスを Nginx 側で受けるだけですinternal って付けるのがポイントです。そうすると、このように内部からしか参照できなくなります。外からそのパスを叩いても見れないということになります。
Rails2以前の場合は自分でヘッダに値を設定する必要があり、Rails3以降は設定を変更するだけでいけるようです。
# Rails2以前 def download # 認証処理などを挟むことができます。 path = "/bigfiles/long_movie.mp4" response.headers['X-Accel-Redirect'] = path response.headers['Content-Type'] = "application/force-download" response.headers['Content-Disposition'] = "attachment; filename=\"#{File.basename(path)}\"" response.headers['Content-length'] = File.size(RAILS_ROOT + path) render :nothing => true end # Rails3 def download # 認証処理などを挟むことができます。 path = "/bigfiles/long_movie.mp4" send_file path, :type => "application/force-download", :disposition => "attachment; filename=\"#{File.basename(path)}\"" end # config/environments/production.rb # 下記行をコメントアウト (Apache, lighttpd の場合はこの行を使う) # config.action_dispatch.x_sendfile_header = "X-Sendfile" # 下記の行を有効にする (nginxの場合はこの行を使う) config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
location / {
client_max_body_size 200m;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_pass http://railsapp;
}
location /bigfiles {
# -> /path/to/railsroot/bigfiles
root /path/to/railsroot/;
internal;
}
gist に上げてあります。https://gist.github.com/708959
補足
逆に、ちょっとしたアプリを動かすときに、いちいち nginx の設定とかせずに Unicorn とかから直接ファイルを送りたい場合もあります。Rails3になってから、config/environments/productioin.rb がデフォルトのままだと send_file すると 0bytes になってしまいます。
下記の2行をコメントアウトしておくと、Unicorn なりで直接ファイル送信ができるようになります。
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
ついでに、静的ファイルも Unicorn なりで表示したいような手抜き構成のときは、下記の設定もお忘れなく。
config.serve_static_assets = false




