javascript - 从 Java Spring 下载 - OpenWith/Save 对话框在完成之前不会出现
问题描述
问题: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 后端下载 Angular 文件- 此人说他有一个解决方法,但没有提供。我试图根据他的回答进行实验,但没有运气。
使用 HTML5/Javascript 生成和保存文件- 这似乎只是解决了下载客户端内容的问题。
还有许多其他示例,但除了第一个链接,这是一个被否决的问题,我找不到任何特定于我的问题的东西。
编辑:根据评论的指导,我切换到GET
from POST
,但经历了相同的行为。
解决方案
推荐阅读
- c# - 在 Blazor 的客户端上播放声音?
- android - qt/qml android 虚拟键盘 z 位置
- javascript - 带有 JQuery 分配的 DOM 动画和效果的 IF 语句存在问题
- asp.net - ASP.NET Core 多线程应用程序中的 addScoped 服务生命周期
- angular - Angular Material Icons 在图标渲染之前显示图标名称
- sql-server - 数据清理后收缩数据库
- python - 调用 get_absolute_url 时出现永久链接错误
- pyjwt - 如何使用 ES256 签署 JWT?
- c++ - 在 C++ 中使用模板的不完整类
- stenciljs - 如何在模具中创建指向同一组件的链接?