サーブレットでファイルをダウンロードする例
1. 概要
Webアプリケーションの一般的な機能は、ファイルをダウンロードする機能です。
このチュートリアルでは、we’ll cover a simple example of creating a downloadable file and serving it from a Java Servlet application。
使用しているファイルは、webappリソースからのものです。
2. Mavenの依存関係
If using Java EE, then we wouldn’t need to add any dependencies.ただし、Java SEを使用している場合は、javax.servlet-apiの依存関係が必要になります。
javax.servlet
javax.servlet-api
4.0.1
provided
依存関係の最新バージョンはhereにあります。
3. サーブレット
最初にコードを見てから、何が起こっているのかを調べましょう。
@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
private final int ARBITARY_SIZE = 1048;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/plain");
resp.setHeader("Content-disposition", "attachment; filename=sample.txt");
try(InputStream in = req.getServletContext().getResourceAsStream("/WEB-INF/sample.txt");
OutputStream out = resp.getOutputStream()) {
byte[] buffer = new byte[ARBITARY_SIZE];
int numBytesRead;
while ((numBytesRead = in.read(buffer)) > 0) {
out.write(buffer, 0, numBytesRead);
}
}
}
}
3.1. エンドポイントのリクエスト
@WebServlet(“/download”)アノテーションは、“/download” end-pointに向けられた要求を処理するためにDownloadServletクラスをマークします。
または、web.xmlファイルにマッピングを記述することでこれを行うことができます。
3.2. 応答Content-Type
HttpServletResponseオブジェクトには、setContentTypeというメソッドがあり、これを使用してHTTP応答のContent-Typeヘッダーを設定できます。
Content-Typeは、ヘッダープロパティの履歴名です。 別の名前はMIMEタイプ(Multipurpose Internet Mail Extensions)です。 ここでは、単に値をメディアタイプと呼びます。
This value could be “application/pdf”, “text/plain”, “text/html”, “image/jpg”, etc.、公式リストはInternet Assigned Numbers Authority(IANA)によって管理されており、hereで見つけることができます。
この例では、単純なテキストファイルを使用しています。 The Content-Type for a text file is “text/plain”.
3.3. 応答Content-Disposition
応答オブジェクトにContent-Disposition headerを設定すると、アクセスしているファイルの処理方法がブラウザに指示されます。
ブラウザはContent-Dispositionの使用を慣例として理解していますが、実際にはHTTP標準の一部ではありません。 W3には、hereを読み取るために使用できるContent-Dispositionの使用に関するメモがあります。
応答の本体のContent-Disposition値は、「インライン」(レンダリングされるWebページコンテンツの場合)または「添付ファイル」(ダウンロード可能なファイルの場合)のいずれかになります。
指定しない場合、デフォルトのContent-Dispositionは「インライン」です。
オプションのヘッダーパラメータを使用して、ファイル名「sample.txt」を指定できます。
ブラウザによっては、指定されたファイル名を使用してすぐにファイルをダウンロードするものと、定義済みの値を含むダウンロードダイアログが表示されるものがあります。
実行される正確なアクションは、ブラウザーによって異なります。
3.4. ファイルからの読み取りと出力ストリームへの書き込み
コードの残りの行では、リクエストからServletContextを取得し、それを使用して「/WEB-INF/sample.txt」にあるファイルを取得します。
次に、HttpServletResponse#getOutputStream()を使用して、リソースの入力ストリームから読み取り、応答のOutputStreamに書き込みます。
使用するバイト配列のサイズは任意です。 InputStreamからOutputStreamにデータを渡すために割り当てるのに妥当なメモリの量に基づいて、サイズを決定できます。核が小さいほど、ループが多くなります。数値が大きいほど、メモリ使用量が多くなります。
このサイクルは、ファイルの終わりを示すnumByteReadが0になるまで続きます。
3.5. 閉じるとフラッシュ
Streamインスタンスは、現在保持しているリソースを解放するために、使用後に閉じる必要があります。 残りのバッファバイトを宛先に書き込むには、Writerインスタンスもフラッシュする必要があります。
try-with-resourcesステートメントを使用すると、アプリケーションは、tryステートメントの一部として定義されたAutoCloseableインスタンスを自動的にcloseします。 try-with-resourceshereの詳細をご覧ください。
これらの2つの方法を使用してメモリを解放し、準備したデータがアプリケーションから送信されるようにします。
3.6. ファイルをダウンロードする
すべてが整ったところで、サーブレットを実行する準備ができました。
ここで、相対エンドポイント“/download”にアクセスすると、ブラウザはファイルを「simple.txt」としてダウンロードしようとします。
4. 結論
サーブレットからファイルをダウンロードするのは簡単なプロセスになります。 ストリームを使用すると、データをバイトとして渡すことができ、メディアタイプはクライアントブラウザーにどのタイプのデータが期待されるかを通知します。
応答の処理方法を決定するのはブラウザの責任ですが、Content-Dispositionヘッダーを使用していくつかのガイドラインを示すことができます。
この記事のすべてのコードは、over on GitHubにあります。