Zip-файл как вход и выход для REST API - PullRequest
1 голос
/ 28 февраля 2020

Я пытаюсь создать 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.

Возможно, данные все еще где-то кешируются, и я неправильно подхожу к этому. Как я могу улучшить это решение и почему оно так медленно работает с большим количеством файлов, а не с несколькими большими файлами?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...