参考にさせていただいた内容をもとに、以下のように実装しました。
※パラメータの inputStream は MultipartFile から作成したもので、zip ファイルです。
バイト配列の取得位置が try-with-resources ではまだ ZipOutputStream を close していない場所だったので、ret = baos.toByteArray(); の前に、明示的に zipOutStream.close(); を入れました。
これで、7-zipの場合の解凍時のペイロードのメッセージも無くなり、また、Windowsエクスプローラでのダブルクリックでも解凍できるようになりました。
public byte[] sampleZip(InputStream inputStream) {
byte[] ret = new byte[1048476];
ZipEntry zipEntry;
ZipEntry zipOutputEntry;
try (ZipInputStream zipInStream = new ZipInputStream(new BufferedInputStream(inputStream),
Charset.forName("SJIS"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zipOutStream = new ZipOutputStream(baos);) {
while ((zipEntry = zipInStream.getNextEntry()) != null) {
if (zipEntry.isDirectory()) {
continue;
}
String entryName = FilenameUtils.getName(zipEntry.getName()); // FilenameUtils:独自のクラス
String fileName = FilenameUtils.getBaseName(entryName);
String fileExt = FilenameUtils.getExtension(entryName);
SCOPE: {
if (StringUtils.isEmpty(fileName)
|| fileName.length() < 5
|| StringUtils.isEmpty(fileExt)) {
break SCOPE;
}
byte[] fileBin = IOUtils.toByteArray(zipInStream);
if (fileBin.length <= 0) {
break SCOPE;
}
if (!(fileExt.equals("xls") || fileExt.equals("xlsx"))) {
zipOutputEntry = new ZipEntry(entryName);
zipOutputEntry.setSize(fileBin.length);
zipOutStream.putNextEntry(zipOutputEntry);
zipOutStream.write(fileBin);
break SCOPE;
}
XSSFWorkbook workbook = new XSSFWorkbook();
workbook = addSheet(new ByteArrayInputStream(fileBin)); // addSheet:独自の関数
fileBin = getBytes(workbook);
if (workbook != null) {
workbook.close();
zipOutputEntry = new ZipEntry(entryName);
zipOutputEntry.setSize(fileBin.length);
zipOutStream.putNextEntry(zipOutputEntry);
zipOutStream.write(fileBin);
}
}
zipInStream.closeEntry();
zipOutStream.closeEntry();
}
zipOutStream.close(); //追加 2020.03.05
ret = baos.toByteArray();
} catch (Exception e) {
ret = null;
}
return ret;
}