Я пытаюсь создать API, который принимает файл .zip, выполняет некоторые вычисления над данными файла и возвращает файл .zip пользователю с теми же файлами плюс один дополнительный сгенерированный файл. Моя идея состояла в том, чтобы использовать поток и выполнять вычисления для архивирования содержимого файла при поступлении данных и последующей его передачи.
У меня есть метод контроллера:
@RequestMapping(value = "/sign", consumes = "application/zip", produces = "application/zip", method = RequestMethod.POST)
public void calculate(HttpServletRequest request, HttpServletResponse response) throws Exception {
response.setStatus(HttpServletResponse.SC_OK);
response.addHeader("Content-Disposition", "attachment; filename=\"result.zip\"");
ZipOutputStream responseOutputStream = new ZipOutputStream(response.getOutputStream());
byte[] calculationResult = calculationService.doCalculations(request.getInputStream(), responseOutputStream);
//Write some more stuff to responseOutputStream based on calculations result
request.getInputStream().close();
responseOutputStream.close();
}
и служба Метод:
public byte[] doCalculations(InputStream zipFileStream, ZipOutputStream outputStream) throws Exception {
ByteArrayOutputStream calculationResultStream = new ByteArrayOutputStream();
ZipInputStream zipInputStream = new ZipInputStream(zipFileStream);
ZipEntry zipEntry = zipInputStream.getNextEntry();
while (zipEntry != null) {
//Output entry
ZipEntry zipOutEntry = new ZipEntry(zipEntry.getName());
outputStream.putNextEntry(zipOutEntry);
int bytesRead;
byte[] tempBuffer = new byte[8192 * 10];
while ((bytesRead = zipInputStream.read(tempBuffer)) != -1) {
outputStream.write(tempBuffer, 0, bytesRead);
}
//Do some quite light calculations
//calculationResultStream.write(byte[] calcRes);
zipEntry = zipInputStream.getNextEntry();
}
calculationResultStream.close();
return calculationResultStream.toByteArray();
}
У меня была идея никогда ничего не записывать в память, чтобы избежать нехватки памяти большими файлами. Когда я даю ему файл .zip с одним большим (2 ГБ) файлом, он обрабатывает его за ~ 25 секунд, но проблема возникает, когда я даю файл .zip, содержащий 1000 маленьких файлов (размером 1-5 МБ каждый), а затем работает около 10 минут и делает Postman cra sh.
Возможно, данные все еще где-то кешируются, и я неправильно подхожу к этому. Как я могу улучшить это решение и почему оно так медленно работает с большим количеством файлов, а не с несколькими большими файлами?