Spring boot: загружайте заархивированные большие файлы, пока они обрабатываются на сервере

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

@RequestMapping(value = "{analyseId}/download", method = RequestMethod.GET, produces = "application/zip")
public ResponseEntity<Resource> download(@PathVariable List<String> paths) throws IOException {

    String zipFileName = "zipFiles.zip";
    File zipFile = new File(zipFileName);
    FileOutputStream fos = new FileOutputStream(zipFile);
    ZipOutputStream zos = new ZipOutputStream(fos);
    for (String path : paths) {
        InputStream fis = azureDataLakeStoreService.readFile(path);
        addToZipFile(path , zos, fis);
    }
    zos.close();
    fos.close();
    BufferedInputStream zipFileInputStream = new BufferedInputStream(new FileInputStream(zipFile.getAbsolutePath()));
    InputStreamResource resource = new InputStreamResource(zipFileInputStream);
    zipFile.delete();

    return ResponseEntity.ok()
            .header(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION)
            .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename = " + zipFileName)
            .contentType(MediaType.parseMediaType("application/octet-stream"))
            .body(resource);
}

private static void addToZipFile(String path, ZipOutputStream zos, InputStream fis) throws IOException {
    ZipEntry zipEntry = new ZipEntry(FilenameUtils.getName(path));
    zos.putNextEntry(zipEntry);
    byte[] bytes = new byte[1024];
    int length;
    while ((length = fis.read(bytes)) >= 0) {
        zos.write(bytes, 0, length);
    }
    zos.closeEntry();
    fis.close();
}

Однако в Azure для тайм-аута запроса установлено значение 230 секунд и не может быть изменено, однако для больших файлов требуется больше времени, чтобы загрузить и затем заархивировать файлы на сервере, поэтому соединение с клиентом будет потеряно.

Итак, мой вопрос в том, что, поскольку я получаю данные из потока, можем ли мы выполнять все эти операции одновременно, означает получение потока и его загрузку в одно и то же время, не дожидаясь получения всего файла, или если есть какая-либо другая идея. любой орган, поделитесь этим здесь, пожалуйста.

Спасибо.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
2 389
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ответ заключается в том, чтобы не загружать файл на сервер, а затем отправлять его клиенту, а передавать его клиенту напрямую, вот код

@RequestMapping(value = "/download", method = RequestMethod.GET)
public StreamingResponseBody download(@PathVariable String path) throws IOException {

    final InputStream fecFile = azureDataLakeStoreService.readFile(path);
    return (os) -> {
        readAndWrite(fecFile, os);
    };
}

private void readAndWrite(final InputStream is, OutputStream os)
        throws IOException {
    byte[] data = new byte[2048];
    int read = 0;
    while ((read = is.read(data)) >= 0) {
        os.write(data, 0, read);
    }
    os.flush();
}

Я также добавил эту конфигурацию в ApplicationInit:

@Configuration
public static class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        configurer.setDefaultTimeout(-1);
        configurer.setTaskExecutor(asyncTaskExecutor());
    }

    @Bean
    public AsyncTaskExecutor asyncTaskExecutor() {
        return new SimpleAsyncTaskExecutor("async");
    }

}

Другие вопросы по теме