Angular не загружает файл из потока (StreamingResponseBody) - PullRequest
0 голосов
/ 19 ноября 2018

Я использую angular для загрузки больших файлов, для бэкэнда я использую весеннюю загрузку, вот код конечной точки:

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

    final InputStream file =azureDataLakeStoreService.readFile(path);
    return (os) -> {
        readAndWrite(file , 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) {
        System.out.println("appending to file");
        os.write(data, 0, read);
    }
    os.flush();
}

Когда я пытаюсь получить файл с помощью curl itработает, и я вижу загружаемый файл и его размер увеличивается:

curl -H "Authorization: Bearer <MyToken>" http://localhost:9001/rest/api/analyses/download --output test.zip

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

this.http.get(url, { headers: headers, responseType: 'blob', observe: 'response' })
    .subscribe(response => {
        const contentDispositionHeader: string = response.headers.get('Content-Disposition');
        const parts: string[] = contentDispositionHeader.split(';');
        const filename = parts[1].split('=')[1];
        const blob = new Blob([response.body], {
            type: 'application/zip'
        });
        saveAs(blob, filename);
    });

saveAs () принадлежат file-saver , кстати, приведенный выше код работает, когда я пытаюсь загрузить файл в виде байта [] (без потоковой передачи).

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

ОБНОВЛЕНИЕ :

Я вижу, что файл загружается на вкладке сети Google Chrome, но я понятия не имею, где файл сохраняется.

enter image description here

Ответы [ 2 ]

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

Кажется, что я пропустил arround с заголовками, при сохранении, это финальная версия, это может помочь кому-то еще:

Пружинный ботинок

Добавить эти конфигурации в 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");
    }

}

А это к вашему контроллеру:

@RequestMapping(value = "{analyseId}/download", method = RequestMethod.GET, produces = "application/zip")
public ResponseEntity<StreamingResponseBody> download(@PathVariable Long analyseId) throws IOException {
    try {
        Analyse analyse = analyseService.getAnalyse(analyseId);

        final InputStream file =azureDataLakeStoreService.readFile(analyse.getZippedFilePath());
        Long fileLength = azureDataLakeStoreService.getContentSummary(analyse.getZippedFilePath()).length;
        StreamingResponseBody stream = outputStream ->
                readAndWrite(file , outputStream);

        String zipFileName = FilenameUtils.getName(analyse.getZippedFilePath());
        return ResponseEntity.ok()
                .header(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION)
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + zipFileName)
                .contentLength(fileLength)
                .contentType(MediaType.parseMediaType("application/zip"))
                .body(stream);
    } catch (Exception e) {
        e.printStackTrace();
        return ExceptionMapper.toResponse(e);
    }
}

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();
}

Угловая

download(id) {
    let url = URL + '/analyses/' + id + '/download';
    const headers = new HttpHeaders().set('Accept', 'application/zip');
    const req = new HttpRequest('GET', url, {
        headers: headers,
        responseType: 'blob',
        observe: 'response',
        reportProgress: true,
    });
    const dialogRef = this.dialog.open(DownloadInProgressDialogComponent);
    this.http.request(req).subscribe(event => {
        if (event.type === HttpEventType.DownloadProgress) {
            dialogRef.componentInstance.progress = Math.round(100 * event.loaded / event.total) // download percentage
        } else if (event instanceof HttpResponse) {
            dialogRef.componentInstance.progress = 100;
            this.saveToFileSystem(event, 'application/zip');
            dialogRef.close();
        }
    });
}

private saveToFileSystem(response, type) {
    const contentDispositionHeader: string = response.headers.get('Content-Disposition');
    const parts: string[] = contentDispositionHeader.split(';');
    const filename = parts[1].split('=')[1];
    const blob = new Blob([response.body], {
        type: type
    });
    saveAs(blob, filename);
}
0 голосов
/ 19 ноября 2018

Я пытался использовать ваш бэкэнд-код, но в угловом я использовал это:

window.location.href = "http://localhost:9001/rest/api/analyses/download";

И загрузка начинается успешно.

...