浏览器在下载文件时没有显示下载进度条

5
我是一名有用的助手,可以为您翻译文本。
我有一个带有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文件的截图。服务器正在发送数据,但下载进度条没有出现。

The size keeps incrementing, but there's no progress indication

一旦下载完成,文件将出现在屏幕底部的下载栏中。

The file shows up but only at the end

我该如何将文件发送到浏览器,以便向用户显示此指示器?
非常感谢。
编辑:
正如@CodeCaster所指出的那样,重定向到URL可能有效,但是我的URL受到保护,只有连接的用户才能下载文件。

3
这是因为你的JS正在下载文件,将blob附加到文档中,然后再下载blob。只有最后一部分会触发下载栏。你为什么要这样做?为什么不直接将用户重定向到下载URL? - CodeCaster
我忽略了一件非常重要的事情:我希望我的下载链接是安全的,只有经过身份验证的用户才能下载文件。我编辑了我的问题,以使其更清晰明了。 - Antoine Delia
@Antoine,即使您现在尝试的方式,用户也可以看到下载URL,就像您在第一张截图中看到的那样。您不能依赖用户不查看其开发人员工具作为安全方法。您应该使用基于cookie或单次使用令牌的身份验证来下载文件,并简单地将用户重定向到正确的URL,让浏览器下载文件。 - Arcanox
@briman0094。当然可以,我的意思是如果你尝试从另一个窗口(未登录应用程序)访问URL,服务器将会响应401错误。 - Antoine Delia
如果您重定向用户,情况仍将如此。重定向将包括任何会话cookie,但在非登录窗口中打开URL则不会。唯一的区别是一个请求是XHR,而另一个是导航请求。 - Arcanox
1个回答

2
在Angular方面,只需使用锚标签并在href属性中传递API URL。
<a href = {this.apiUrl + '/downloadFile' + '?' + 'your params'}>Download</a>

在数据流传输之前,以及服务器端,确保您设置了以下响应头。

res.setHeader('content-length',data.ContentLength)  (optional)
res.setHeader('content-type', mimetype);
res.setHeader('content-disposition', 'attachment; filename');

这部分负责在新标签页中打开下载,关闭它并显示下载进度条(异步下载)。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接