Я хочу сжать динамически созданный контент и напрямую написать ServletOutputStream, не сохраняя его как файл на сервере перед сжатием.
Например, я создал книгу Excel и StringBuffer, которая содержит строки с шаблоном SQL. Я не хочу сохранять динамический контент в файлы.xlsx и.sql на сервере перед тем, как заархивировать файлы и записать в ServletOutputStream для загрузки.
Образец кода:
ServletOutputStream out = response.getOutputStream();
workbook.write(byteArrayOutputStream);
zipIt(byteArrayOutputStream,out);
public static boolean zipIt(ByteArrayOutputStream input, ServletOutputStream output) {
try {
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(output));
ZipEntry zipEntry = new ZipEntry("test.xlsx");
zos.putNextEntry(zipEntry);
if (input != null) {
zipEntry.setSize(input.size());
zos.write(input.toByteArray());
zos.closeEntry();
}
} catch (IOException e) {
logger.error("error {}", e);
return false;
}
return true;
}
Создайте HttpServlet
и в методе doGet()
или doPost()
создайте ZipOutputStream
инициализированный ServletOutputStream
и напишите непосредственно ему:
resp.setContentType("application/zip");
// Indicate that a file is being sent back:
resp.setHeader("Content-Disposition", "attachment;filename=test.zip");
// workbook.write() closes the stream, so we first have to
// write it to a "buffer", a ByteArrayOutputStream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
workbook.write(baos);
byte[] data = baos.toByteArray();
try (ZipOutputStream out = new ZipOutputStream(resp.getOutputStream())) {
// Here you can add your content to the zip
ZipEntry e = new ZipEntry("test.xlsx");
// Configure the zip entry, the properties of the file
e.setSize(data.length);
e.setTime(System.currentTimeMillis());
// etc.
out.putNextEntry(e);
// And the content of the XLSX:
out.write(data);
out.closeEntry();
// You may add other files here if you want to
out.finish();
} catch (Exception e) {
// Handle the exception
}
}
Exception
изout.closeEntry()
:java.io.IOException: Stream closed
workbook.write()
закрывает поток, поэтому сначала нужно записать его в «буфер»,ByteArrayOutputStream
. Отредактировал мой ответ.