Проблема: диалоговое окно Открыть с / Сохранить файл не появляется, пока не завершится запрос POST
.Пользователь щелкает ссылку на скачивание, затем через X минут (X увеличивается с размером файла) открывается диалоговое окно Открыть с / Сохранить файл.Я ожидал, что диалоговое окно появится сразу, а ход будет отслеживаться немедленно, а не после того, как запрос будет завершен.
Вопрос: Как я могу обеспечить немедленное представление пользователя с помощью Открыть с помощью/ Диалоговое окно / Сохранить, и процесс загрузки сразу отображается в меню «Загрузка» браузера, а не после того, как запрос POST
завершен?
Код клиента (угловой):
downloadFile(){
this.documentApi.postDownloadFile(this.fileId).subscribe(data => {
var link = document.createElement("a");
link.href = window.URL.createObjectURL(data);
link.download= this.fileName;
link.dispatchEvent(new MouseEvent(`click`, {bubbles: true, cancelable: true, view: window}));
});
}
postDownloadFile(id): Observable<any> {
let httpOptions = {
headers: new HttpHeaders({
'Accept': 'text/html, application/xhtml+xml, */*',
'Content-Type': 'application/octet-stream'
}),
responseType: 'blob' as 'blob'
};
return this.http.post(`${BaseUrl}reviewDocument/downloadFile`, id, httpOptions).pipe(
catchError(this.handleError)
);
}
JavaКод:
@RequestMapping(value="/reviewDocument/downloadFile", method = RequestMethod.POST, produces="application/octet-stream")
public void downloadFile(HttpServletResponse response, @RequestBody String fileId) throws IOException {
try{
File file = new File(getFilePath(fileId));
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getName()));
response.setContentLength((int)file.length());
InputStream inputStream = new FileInputStream(file);
int read=0;
byte[] bytes = new byte[1024];
OutputStream os = response.getOutputStream();
while((read = inputStream.read(bytes))!= -1){
os.write(bytes, 0, read);
}
os.flush();
os.close();
}
catch(Exception ex){
System.out.println(ex);
}
}
Изначально я возвращал файл так: return ResponseEntity.ok().body(FileCopyUtils.copyToByteArray(inputStream));
, и это вызывало ошибки нехватки памяти при большом размере файла.
Проблема с нехваткой памяти, похоже, была решена с помощью Outputstream
.Я также пытался использовать IOUtils
, но похоже, что это то же самое, что и запись в выходной поток, и, поскольку я больше не сталкиваюсь с ошибками нехватки памяти, я больше не проводил рефакторинг.
Независимо от того, какое бы решение я ни пытался, запрос «Открыть с помощью / сохранить файл» задерживается до полного завершения запроса.Ничего не отображается в меню загрузки браузера.Для изображений, PDF-файлов и т. Д. Это не является проблемой, поскольку размер файла небольшой, поэтому запрос занимает меньше времени, но всякий раз, когда обслуживается большой файл, эта проблема заметна, поскольку запрос занимает больше времени.
Изучение других вопросов SO:
Загрузка угловых файлов из бэкэнда RestFul Java Spring - Этот человек говорит, что у него есть обходной путь, но он его не предоставляет.Я пытался экспериментировать, основываясь на его ответе, но безуспешно.
Использование HTML5 / Javascript для генерации и сохранения файла - Похоже, что это просто решение проблемы загрузки контента на стороне клиента.
Существует множество других примеров, но, за исключением первой ссылки, которая является вопросом с отрицательным голосом, я не могу найти ничего конкретного для своей проблемы.
Редактировать: Основываясь на рекомендациях из комментариев, я переключился на GET
с POST
, но испытал то же самое поведение.