26

応答ストリームに直接書き込むファイルをダウンロードするために ASP.NET HttpHandler を使用してテストを行っていますが、その方法についてはよくわかりません。これはメソッドの例です。将来、ファイルはデータベースの BLOB に格納される可能性があります。

        public void GetFile(HttpResponse response)
    {
        String fileName = "example.iso";
        response.ClearHeaders();
        response.ClearContent();
        response.ContentType = "application/octet-stream";
        response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName);
        using (FileStream fs = new FileStream(Path.Combine(HttpContext.Current.Server.MapPath("~/App_Data"), fileName), FileMode.Open))
        {
            Byte[] buffer = new Byte[4096];
            Int32 readed = 0;

            while ((readed = fs.Read(buffer, 0, buffer.Length)) > 0)
            {
                response.OutputStream.Write(buffer, 0, readed);
                response.Flush();
            }
        }
    }

しかし、これが正しいのか、それとももっと良い方法があるのか​​ はわかりません。私の質問は次のとおりです。

  1. ブラウザでURLを開くと「ファイルの保存」ダイアログが表示されますが、「保存」をクリックする前にサーバーがストリームへのデータのプッシュを開始しているように見えますが、これは正常ですか?
  2. "response.Flush()" という行を削除すると、ブラウザで URL を開いたときに ... Web サーバーがデータをプッシュしているのがわかりますが、[ファイルの保存] ダイアログが表示されません (または少なくとも合理的な時間の方法ではありません)なぜですか?
  3. WebRequest オブジェクトで URL を開くと、ストリームを読み取ってファイルを取得できますが、HttpResponse.ContentLength が「-1」であることがわかります。-1 とはどういう意味ですか? HttpResponse.ContentLength が応答の長さを表示するのはいつですか? たとえば、deflate で圧縮された大きな xml をバイナリ ストリームとして取得するメソッドがあるのですが、その場合は... WebRequest でアクセスすると、HttpResponse で ContentLength とストリームの長さが実際にわかります、 どうして?
  4. Web サーバーで最適なパフォーマンスを得るためにバッファーとして使用する Byte[] 配列の最適な長さはどれくらいですか? 4K から 8K の間であると読みましたが、正しい決定を下すにはどの要素を考慮する必要がありますか。
  5. この方法は、IIS またはクライアントのメモリ使用量を増大させますか? それとも実際に転移を正しくバッファリングしていますか?

非常に多くの質問をして申し訳ありません。私は Web 開発の新人です :P

乾杯。

4

3 に答える 3

17
  1. はい; これは正常です。
  2. フラッシュしないと、サーバーが終了するまでブラウザーは応答を受け取りません (Content-Dispositionヘッダーでさえありません)。したがって、ファイルダイアログを表示することを知りません。
  3. ヘッダーはContent-Length、応答全体がバッファリングされている場合 (フラッシュしない場合)、または自分で設定した場合にのみ設定されます。この場合、自分で設定できますし、設定する必要があります。書きます

    response.AppendHeader("Content-Length", new FileInfo(path).Length.ToString());
    
  4. 4K をお勧めします。推奨に確固たる根拠はありません。
  5. この方法は、それを行うための最良の方法です。Flushループ内で呼び出すことにより、バッファリングなしで応答をすぐにネットワークに送信します。ただし、パフォーマンスを向上させるために、GZIP 圧縮を使用できます。
于 2010-04-02T21:48:19.367 に答える
2
  1. はい、バッファリングです。
  2. Flush は、キャッシュされたコンテンツをブラウザーにプッシュします。プッシュされない場合、保存ダイアログ ボックスは表示されません。
  3. 使用している正確なファイル/URL/ストリームを見ないとわかりません。
  4. 要因は、実際にはページの遅さに依存すると思います。4k に向けてパフォーマンスが向上します。そしておそらく、低速の接続に対応するには、値が小さい方がよいでしょう。
  5. #1 & 2 を参照してください。
于 2010-04-02T21:42:36.430 に答える
2

#3 については、http 応答で content-length ヘッダーを設定する必要があります。これらの値の多くは、http ヘッダーから取得されます。

応答オブジェクトのバッファリング プロパティを false に変更することで、バッファリングを変更できると思います。しばらくやってないからどうだったか覚えてない。

于 2010-04-02T21:47:47.690 に答える