【发布时间】:2019-08-26 01:45:11
【问题描述】:
我有一个带有 ASP.NET Web API 的 Angular 应用程序。
我想下载存储在我的服务器上的文件。目前,这是我拥有的代码:
[HttpGet]
[Route("downloadFile")]
[JwtAuthentication] //Only a connected user can download the file
public async Task<HttpResponseMessage> DownloadFile(string path)
{
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var fileStream = File.OpenRead(path);
result.Content = new StreamContent(fileStream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentLength = fileStream.Length;
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = fileStream.Name,
Size = fileStream.Length
};
return result;
}
在我的 Angular 代码中:
// file-navigation.service.ts
downloadFile(file: FileElement) {
const data = { path: this.formatPath(true) + file.name };
return this.http.get(this.apiUrl + '/downloadFile', { params: data, responseType: 'blob' });
}
// file-navigation.component.ts
this.fileNavigationService.downloadFile(element).subscribe(result => {
this.generateDownload(element, result, false);
});
generateDownload(element: FileElement, blob: Blob, isArchive: boolean) {
const fileName = element != null ? element.name : 'Archive';
if (navigator.appVersion.toString().indexOf('.NET') > 0) {
window.navigator.msSaveBlob(blob, fileName + (isArchive ? '.zip' : ''));
} else {
const link = document.createElementNS(
'http://www.w3.org/1999/xhtml',
'a'
);
(link as any).href = URL.createObjectURL(blob);
(link as any).download = fileName + (isArchive ? '.zip' : '');
document.body.appendChild(link);
link.click();
setTimeout(function () {
document.body.removeChild(link);
link.remove();
}, 100);
}
}
有了这个,我成功地从服务器下载了一个文件。
但是,Chrome 中的下载栏仅在下载完成后才会出现。因此,如果文件太大,用户将不会得到任何指示他的文件当前正在下载。
下面是正在下载的 16Mb 文件的屏幕截图。服务器当前正在发送数据,但没有出现下载栏。
然后,一旦下载完成,文件就会出现在屏幕底部的下载栏中。
如何将文件发送到浏览器,以便它向用户显示此指示器?
非常感谢。
编辑:
正如@CodeCaster 指出的那样,重定向到 URL 可以工作,但是,我的 URL 受到保护,因此只有连接的用户才能下载文件。
【问题讨论】:
-
那是因为你的 JS 正在下载文件,将 blob 附加到文档中,然后下载 blob。只有最后一部分会触发下载栏。你为什么这样做?为什么不简单地将用户重定向到下载 URL?
-
我忽略了一些非常重要的内容:我希望我的下载 URL 受到保护,以便只有经过身份验证的用户才能下载文件。我编辑了我的问题,以便更清楚。
-
@Antoine 下载 URL 将对用户可见,即使您现在尝试这样做,正如您在第一个屏幕截图中看到的那样。您不能依赖用户不将其开发人员工具视为一种安全方法。您应该使用基于 cookie 或基于一次性令牌的身份验证来下载文件,只需将用户重定向到正确的 URL 并让浏览器下载文件。
-
@briman0094。是的,当然,我的意思是,如果您尝试从另一个窗口(未登录应用程序)访问 URL,服务器将响应 401 错误。
-
如果您重定向用户,情况仍然如此。重定向将包括任何会话 cookie,但在未登录的窗口中打开 URL 不会。唯一的区别是一个请求是 XHR,而另一个是导航请求。
标签: c# asp.net angular file asp.net-web-api