Весенняя загрузка: загрузка сжатых больших файлов во время их обработки на сервере - PullRequest
0 голосов
/ 15 ноября 2018

В моем приложении я заархивирую, а затем загружаю большие файлы, файлы расположены в лазури, поэтому я читаю файлы из потока, а затем архивирую их один за другим, чтобы я мог загрузить файл 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 секунд, и нельзя изменить , однако для больших файлов требуется больше, чем длязагрузите, а затем заархивируйте файлы на сервере, чтобы тем временем соединение с клиентом было потеряно.

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

Спасибо.

1 Ответ

0 голосов
/ 19 ноября 2018

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

@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");
    }

}
...