问题:在POST
请求完成之前,“打开方式/保存文件”对话框不会出现。用户将单击下载链接,然后在X分钟(X随着文件大小增加)之后,出现“打开方式/保存文件”对话框。我希望对话框会立即出现,并且可以立即跟踪进度,而不是在请求完成之后。
问题::如何确保立即向用户显示“打开方式/保存”对话框,并在浏览器的“下载”菜单中立即显示下载进度,而不是在{{ 1}}请求完成了吗?
客户代码(角度):
POST
Java代码:
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)
);
}
我最初是这样返回文件的:
@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
,但是这似乎与写入输出流是一样的事情,并且由于我再也没有遇到“内存不足”错误,所以我不再进行重构。
不管我尝试过什么解决方案,打开/保存文件的提示都会延迟到请求完全完成为止。浏览器的“下载”菜单中也未显示任何内容。对于图像和pdf等而言,这不是问题,因为文件很小,因此请求花费的时间更少,但是每当提供大文件时,此问题就很明显,因为请求花费了更长的时间。
研究其他SO问题:
Angular file download from RestFul Java Spring backend-此人说他有一种解决方法,但没有提供。我试图根据他的回答进行实验,但是没有运气。
Using HTML5/Javascript to generate and save a file-这似乎只是解决了下载客户端内容的问题。
还有许多其他示例,但是除了第一个链接(这是一个被否决的问题)之外,我找不到与我的问题有关的任何内容。
编辑:基于评论的指导,我从IOUtils
切换到GET
,但是遇到了相同的行为。