6

私の Web ページ (Rails でレンダリング) で、ユーザーが写真を右クリックしてブラウザーの [名前を付けて保存] ダイアログを表示し、ユーザーが写真をハード ドライブに保存できるようにしたいと考えています。

ただし、サーバー上の写真には、ファイル拡張子のない通常とは異なるファイル名 (長い 16 進名) が付けられています。名前を付けて保存ダイアログのファイル名プロンプトには、この醜いファイル名が表示されます。ユーザーが保存をクリックすると、ファイル拡張子のない不適切な名前のファイルが作成されます。

Web ページ、写真の実際のファイル名 (たとえば、カメラから取得した名前) を認識しています。名前を付けて保存ダイアログのファイル名プロンプトを、選択したファイル名でプログラム的に上書きする方法はありますか?

私はContent-Dispostionヘッダーを認識しており、このヘッダーを介してファイル名を指定できることを知っています。ただし、このヘッダーを利用できるようにするには、ファイル全体をブラウザーにロード/レンダリングする必要があると思います。ダウンロードできるようにするアセットが映画の場合、ファイルのロードによってブラウザがタイムアウトする可能性があります。たとえば、100 メガのビデオの場合です。

考え?

-A

4

4 に答える 4

1

少し前に自分で問題の少なくとも一部に遭遇した(そして解決した)ので、ここで問題を理解していると思います。

私はいくつかの大きな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 ^

于 2010-08-29T00:37:57.503 に答える
0

あなたのコメントに基づいて、いくつかの問題があります。

  1. Rails アプリを使用してファイル名を設定します。
  2. ファイルはリモート ホスト上にあり、Rails アプリは仲介者として機能しています。
  3. ファイルが大きい可能性があるため、ファイル全体をキューに入れるのではなく、受信時にブラウザーに送信する必要があります。

Rails だけでストリーミングするのは、いくつかの理由で注意が必要です。

すべてが揃うまでブロックするのではなく、データの受信時にメッセージ本文にアクセスできる HTTP クライアントが必要です。Net::HTTP はそのクライアントではありません。どのライブラリがより適しているかはわかりません。

ファイルをバラバラにするためのよりイベント駆動型の方法が得られたら、レンダーに proc を渡すことができます。 render :text => proc { |response, output| ... }

outputIO オブジェクトのように使用できます。ただし、一部のサーバーは送信前にバッファリングする場合があるため、注意が必要です。


Rails でバイト シャッフルを処理しない方が簡単です。

Web サーバーまたは Web サーバーの前にあるプロキシが X-REPROXY-URL HTTP ヘッダーをサポートしている場合、アプリケーションはそのヘッダーを設定でき、Web サーバーまたはプロキシはファイルをストリーミングします。

Perlbalは、私が知っている唯一のプロキシ サーバーであり、そのままでそのヘッダーをサポートしています。

Apache2 モジュールも利用できます

于 2010-12-01T06:28:58.663 に答える
0

たとえば、への書き換えなど、スマートなサーバー側の URL 書き換えを行うことができfoo.mpegますyouveryuglyfilenamewithoutextension

于 2010-08-20T19:20:50.903 に答える
0

Content-Disposition を "attachment; filename="... に設定します。問題ありません。「添付ファイル」は、ブラウザでレンダリングされないことを明示的に意味しますが、ファイルの名前変更は機能します (または、特にその場合)。

于 2010-08-20T19:25:05.807 に答える