すべてが正常に機能しますが、ファイルが1MB程度の小さい場合にのみ、ブラウザが表示する20MBなどの大きなファイルで試してみたところ、ダウンロードを強制する代わりに、今まで多くのヘッダーを試しました。
PrintWriter out = response.getWriter();
String fileName = request.getParameter("filename");
File f= new File(fileName);
InputStream in = new FileInputStream(f);
BufferedInputStream bin = new BufferedInputStream(in);
DataInputStream din = new DataInputStream(bin);
while(din.available() > 0){
out.print(din.readLine());
out.print("\n");
}
response.setContentType("application/force-download");
response.setContentLength((int)f.length());
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Disposition","attachment; filename=\"" + "xxx\"");//fileName);
in.close();
bin.close();
din.close();
ファイルの内容を出力ストリームに書き込んだ後、応答ヘッダーを設定しています。これは、ヘッダーを設定する応答ライフサイクルのかなり遅い段階です。操作の正しいシーケンスは、最初にヘッダーを設定してから、ファイルの内容をサーブレットの出力ストリームに書き込むことです。
したがって、メソッドは次のように記述する必要があります(これは単なる表現であるためコンパイルされません)。
response.setContentType("application/force-download");
response.setContentLength((int)f.length());
//response.setContentLength(-1);
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Disposition","attachment; filename=\"" + "xxx\"");//fileName);
...
...
File f= new File(fileName);
InputStream in = new FileInputStream(f);
BufferedInputStream bin = new BufferedInputStream(in);
DataInputStream din = new DataInputStream(bin);
while(din.available() > 0){
out.print(din.readLine());
out.print("\n");
}
失敗の理由は、サーブレットによって送信される実際のヘッダーが、送信しようとしているものと異なる可能性があるためです。結局のところ、サーブレットコンテナーがどのヘッダー(HTTP応答の本文の前に表示されるか)を知らない場合、適切なヘッダーを設定して、応答が有効であることを確認できます。したがって、ファイルが書き込まれた後にヘッダーを設定することは無駄であり、コンテナーが既にヘッダーを設定している可能性があるため、冗長です。 WiresharkまたはFiddlerやWebScarabなどのHTTPデバッグプロキシを使用してネットワークトラフィックを調べると、これを確認できます。
この動作を理解するには、Java ServletResponse.setContentType のEE APIドキュメントを参照することもできます。
応答がまだコミットされていない場合、クライアントに送信される応答のコンテンツタイプを設定します。指定されたコンテンツタイプには、文字エンコーディング仕様が含まれる、たとえば、text/html; charset = UTF-8。 getWriterが呼び出される前にこのメソッドが呼び出された場合、応答の文字エンコーディングは指定されたコンテンツタイプからのみ設定されます。
このメソッドは、コンテンツタイプと文字エンコーディングを変更するために繰り返し呼び出される場合があります。 このメソッドは、応答がコミットされた後に呼び出されても効果がありません。
...
Content-typeおよびその他のヘッダーを設定しますbeforeファイルを書き出します。小さなファイルの場合、コンテンツはバッファリングされ、ブラウザは最初にヘッダーを取得します。大きなものの場合、データが最初に来ます。
これは、テストしたすべてのブラウザーで問題を完全に解決するphpスクリプトからのものです(3.5以降のFF、IE8 +、Chrome)
header("Content-Disposition: attachment; filename=\"".$fname_local."\"");
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($fname));
だから、私が見る限り、あなたはすべてを正しくやっている。ブラウザの設定を確認しましたか?