0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

出力responseの勉強(Apache POI)

Posted at

WorkbookをHTTPレスポンスとしてダウンロードさせる。

Apache POIを使用してWorkbookオブジェクトを作成したと仮定する。
以下は作成済みのWorkbookオブジェクトをダウンロードするメソッドの例だ。

メソッドの例

Apache POIで主に使用するWorkbookオブジェクトはHSSFWorkbook、XSSFWorkbookは2種類ある。
HSSFWorkbookはExcel 97~2003(.xls)を処理する為のクラスで、古い。
XSSFWorkbookはExcel 2007以上(.xlsx) を処理する為のクラス。

HSSFWorkbookはサポートする機能も少ないし、スタイルもその数が制限されている。
色々不便だが、ここではHSSFWorkbookを例とする。

protected void exportXsl(HSSFWorkbook wb, String fileName, HttpServletResponse response) {
    // HTTPレスポンスヘッダーを設定する。
    response.setContentType("application/vnd.ms-excel");
    response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName);

    // ワークブックオブジェクトをレスポンスに書き込む。outとresponseOutputStreamはtry with resourceで対応する。
    try (ByteArrayOutputStream out = new ByteArrayOutputStream();
         OutputStream responseOutputStream = response.getOutputStream()) {
        wb.write(out);
        responseOutputStream.write(out.toByteArray());
        responseOutputStream.flush();  // Flush the response output stream
    } catch (IOException e) {
        // 例外処理
    } finally {
        try {
            wb.close();
        } catch (IOException e) {
            // 例外処理
        }
    }
}

このメソッドがvoidになっている理由はreturn "" や他の戻り値を返すコードを exportXsl メソッドに追加すると、2回レスポンスを送信しようとしてエラーが発生する可能性があるため。
exportXsl メソッド内で response.getOutputStream() を使って、ファイルをクライアントに送信している。この時点でレスポンスが確定し、ファイルが送られるのだ。

パラメーター説明

①HSSFWorkbook wb:作成済みのWorkbook (仮定: HSSFWorkbook)
②String fileName:ファイル名
③HttpServletResponse response:クライアントからダウンロードリクエストが来たら、それに対してHTTPレスポンスを送信するため

try with resource?

外部リソースを使った後に自動的にリソース閉じる仕組みのこと。
try()の括弧の中にリソースを宣言する方法。

try (ResourceType resource = new ResourceType()) {
    // リソースを使った処理
} catch (ExceptionType e) {
    // 例外処理
}

try with resourceをしないと?

リソースを手動で閉じる必要がある。

BufferedReader br = null;
try {
    br = new BufferedReader(new FileReader("file.txt"));
    ...
} catch (IOException e) {
    // 例外処理
} finally {
    if (br != null) {
        try {
            br.close();  // 明示的にリソースを閉じる
        } catch (IOException e) {
            // 閉じる際の例外処理
        }
    }
}

閉じるって?

プログラムが使ったリソース(ファイル、ネットワーク接続、データベース接続など)を使い終わった後に解放する必要がある。無駄にメモリやシステム資源を消費することを防ぐ。
例ではoutとresponseOutputStreamはtry with resourceで対応していて、パラメーターのwbはfinallyブロックを使い、リソースのclose()メソッドを明示的に呼び出してリソースを解放している。

closeとflushの違いは?

flushとは、バッファに溜まっているデータを強制的に出力先に送る操作。バッファとは、データを一時的に保持するメモリ領域。なんで使うかというとI/O操作の効率を上げるため。小さなデータを一度に一つずつ書き込むのではなく、一定量のデータをバッファに溜めてから一度に書き出す。
通常、閉じる際に自動的にflushが行われる。なので、flushが必要な場面はリアルタイムにデータを反映させたい場合やすべてのデータを確実に送信したい場合。

結論:コードの理解

wb.write(out);
responseOutputStream.write(out.toByteArray());
responseOutputStream.flush();
  1. wb.write(out): HSSFWorkbookの内容をByteArrayOutputStream(out)に書き込んで,outはメモリ内のバッファにデータを保持します。
  2. responseOutputStream.write(out.toByteArray()): outに溜まったデータをHttpServletResponseの出力ストリーム(responseOutputStream)に書き込んでいる。
  3. responseOutputStream.flush(): responseOutputStreamに溜まったバッファのデータをクライアントに強制的に送っている。

( ・。。・ )🖐

間違っている内容がありましたら、教えて頂ければ喜びます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?