CSVに出力したファイルをZIPに固めてDLした
今やってる仕事のなかで、はじめて取り組んだ知見があったのでまとめたいと思います。
Javaのサーバサイドフレームワーク「Spring」において、CSVファイルをZIP形式に圧縮してダウンロードしていきます。
CSVファイル作成
対象ファイル(今回はCSVファイル)を作成します。
// 対象データ作成 List<String> names= Arrays.asList("koba", "ayana", "suzuko"); // CSVファイルリスト生成 List<File> files = names.stream() .map(name -> { // ファイル作成 File file = new File(fileName + ".csv"); try (PrintWriter pw = new PrintWriter(new BufferdWriter( new OutputStreamWriter(new FileOutputStream(file), "shift_jis")))) { pw.print(name); pw.print(","); pw.print("\r\n"); // Windowsの改行コード(CR+LF) } }) .collect(Collectors.toList());
日本語文字化け
ここで問題になったのが、ファイルに出力される値およびファイル名が日本語の場合、文字化けしてしまうというもの。
標準のAPIではZIP形式のファイル名のエンコードを変更することができません。
なので、ここではorg.apache.tools.zipのZipOutputStreamを使用していきます。
こいつはエンコードをセットすることが出来るので日本語対応もバッチリ出来るはずです!
Mavenの依存関係にantを追記
<!-- apache-ant --> <dependency> <groupId>org.apache.ant</groupId> <artifactId>ant</artifactId> <version>1.7.1</version> </dependency>
ZIPに圧縮
対象ファイルをZIP形式に圧縮します(ここが肝です)
import org.apache.tools.zip.ZipEntry; import org.apache.tools.zip.ZipOutputStream; // 中略 @RequestMapping(value = "/hogehoge/download", method = { RequestMethod.GET }) public void download(HttpServletResponse response) { try (ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()))) { // エンコードをセット(大事) zos.setEncoding("shift_jis"); files.forEach(file -> { try (InputStream in = new BufferedInputStream(new FileInputStream(f))) { // CSVファイルをzip形式に圧縮するためにセット zos.putNextEntry(new ZipEntry(f.getName)); byte[] b = new byte[1024]; int len; while ((len = in.read(b)) != -1) { // zip形式で書き込む zos.write(b, 0, len); } zos.closeEntry(); } }); } }
ファイルをDLする!
responseのヘッダーに値をセットしましょう。
// レスポンスに値をセット responce.setContentType("application/octet-stream;charset=shift_jis"); responce.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileNamePrefix + ".zip", "UTF-8")); responce.setHeader("Content-Transfer-Encoding", "binary");