/home/by-natures/dev*

ソフトウェア開発者として働く人の技術的なメモ

SpringFramework で OutputStream を扱う

大きなファイルを API を通じて返したい処理があり、そのままだとヒープ領域を圧迫して OOM エラーとなってしまうため、ストリーム処理で逐次データをクライアントへ返却するようにしました。

調べている最中に、まさに質問したかったことを Stackoverflow で発見:

stackoverflow.com

ServletResponse の output stream に書き込めば、一定サイズで flush してくれるので、使う側としては output stream にデータを流し込めさえすれば大丈夫でした。Spring Framework での処理の大枠としては以下の通りです。この API を叩くと、octet stream としてデータを返却するため、ブラウザは処理方法が分からずに受け取ったデータをダウンロードする挙動となります。

@RequestMapping(
  value = "/data",
  method = RequestMethod.GET,
  produces = MediaType.APPLICATION_OCTET_STREAM_VALUE
)
public void getData(HttpServletResponse response) throws IOException {

  response.addHeader("Content-Disposition", "attachment; filename=\"data.txt\"");

  try (ServletOutputStream stream = response.getOutputStream()) {
    // stream にデータを書き込む
  }
}

動作確認に少し手間取りましたが、実装自体は簡単でした。これを調べている中で octet stream の挙動についても学べましたし、web はまだまだ知らないことが多いです。