【发布时间】:2018-03-14 07:34:34
【问题描述】:
我想从我的 RestFul Java 后端下载一个大文件。 Java 后端将分块流式传输文件,请参见以下代码:
String filePath = this.workProgressService.getFilePath(entityId);
Path path = Paths.get(filePath);
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String mimeType = fileNameMap.getContentTypeFor(path.getFileName().toString());
if (mimeType == null) {
mimeType = "application/octet-stream";
}
response.setContentType(mimeType);
response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", path.getFileName().toString()));
FileCopyUtils.copy(Files.newInputStream(path), response.getOutputStream());
服务运行良好。 F.E. 当我在浏览器中进入我的重新端点http://localhost:8080/download 时,会弹出一个文件窗口,我可以下载该文件。
但是当我使用以下代码从角度执行此操作时:
const options = new RequestOptions({responseType: ResponseContentType.Blob});
return this.authHttp.get(this.configurationService.getApiURL() + '/filedownload', options)
.map(response => {
console.log(response.blob());
});
文件完全下载后,最后会触发 blob 的控制台日志。如果我在 Chrome 的开发者控制台中查看请求,我可以看到它先下载整个文件,然后再记录它的响应。这样文件保存对话框在响应出现之前不会打开。
问题是我不能只对 Rest 端点的位置使用 href,因为我需要在 GET 请求中发送授权标头。
如何解决用户可以直接从后端通过对话框下载文件而不必等到浏览器完全下载文件的问题?
【问题讨论】:
-
有什么问题?
-
问题是,我希望在用户点击下载时直接显示下载对话框。不是在整个请求完成并且在浏览器请求中下载 1GB 时。这样当用户下载文件时就没有任何进展了。由于请求需要很长时间,因此用户也没有发生任何事情。
-
我想您需要确保正确获取所有 HTTP 标头,从而帮助您的客户。 Content-disposition 的文件名只能包含 ASCII 字符。我还建议添加 Content-length 标头,因为您已经提前知道文件大小。这使客户端能够呈现适当的进度。而且由于下载对话框是一个非常与浏览器相关的东西,请告诉你正在使用哪个浏览器以及哪个 Angular 版本。
-
感谢您的评论。我已将内容长度添加到标题中。在开发人员控制台中查看时,我还可以在响应中看到正确的标题。我使用的浏览器是 Chrome。但我也用 IE 11 进行了尝试,它具有相同的行为。前端使用 Angular (V4)。当我没有向后端创建 GET 请求但 F.E. 执行 window.location.href 时,将立即显示要下载的文件对话框。
-
好吧,如果你告诉 Angular 发出一个 GET 请求,你会得到响应,但浏览器不会采取任何行动。有道理,不是吗?否则 AJAX 将无法工作,但您会看到大量保存对话框。此处讨论了启动保存对话框:stackoverflow.com/questions/2897619/…,但我猜您尝试找到一种使用 window.location 的方法。通常浏览器对网站进行一次身份验证后,它会自动发送身份验证标头,对吧?
标签: java spring angular rest download