1. 概要

Webアプリケーションの一般的な機能は、ファイルをダウンロードする機能です。

このチュートリアルでは、ダウンロード可能なファイルを作成し、Javaサーブレットアプリケーションから提供する簡単な例について説明します。

使用しているファイルは、webappリソースからのものになります。

2. Mavenの依存関係

Jakarta EEを使用している場合、依存関係を追加する必要はありません。ただし、Java SEを使用している場合は、javax.servlet-api依存関係が必要です。

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

依存関係の最新バージョンはここにあります。

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”)アノテーションは、 DownloadServlet クラスをマークして、“ / download”エンドポイントに向けられたリクエストを処理します。

または、web.xmlファイルにマッピングを記述してこれを行うこともできます。

3.2. 応答Content-Type

HttpServletResponse オブジェクトには、 setContentType というメソッドがあり、これを使用してHTTP応答のContent-Typeヘッダーを設定できます。

Content-Type は、ヘッダープロパティの履歴名です。 別の名前はMIMEタイプ(多目的インターネットメール拡張機能)でした。 ここでは、値を単にメディアタイプと呼びます。

この値は「application/pdf」、「text / plain」、「text / html」、「image / jpg」などです。、公式リストはInternet Assigned Numbers Authority(IANA)によって管理されています。 )およびここで見つけることができます。

この例では、単純なテキストファイルを使用しています。 テキストファイルのコンテンツタイプは「text/plain」です。

3.3. 応答Content-Disposition

応答オブジェクトにContent-Dispositionヘッダーを設定すると、アクセスしているファイルの処理方法がブラウザーに指示されます。

ブラウザは、 Content-Disposition の使用法を慣例として理解していますが、実際にはHTTP標準の一部ではありません。 W3には、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-resourcesの詳細についてはこちらをご覧ください。

これらの2つの方法を使用してメモリを解放し、準備したデータがアプリケーションから確実に送信されるようにします。

3.6. ファイルのダウンロード

すべてが整ったので、サーブレットを実行する準備が整いました。

ここで、相対エンドポイント「/ download」にアクセスすると、ブラウザはファイルを「simple.txt」としてダウンロードしようとします。

4. 結論

サーブレットからのファイルのダウンロードは簡単なプロセスになります。 ストリームを使用すると、データをバイトとして渡すことができ、メディアタイプはクライアントブラウザにどのタイプのデータを期待するかを通知します。

応答の処理方法を決定するのはブラウザの責任ですが、Content-Dispositionヘッダーを使用していくつかのガイドラインを示すことができます。

この記事のすべてのコードは、GitHubにあります。