2017-02-01 184 views
6

我有C#后端和ASP.Net MVC的经验。现在我正在对Angular 2进行第一次尝试。它需要时间,但我最喜欢它。现在我被困在一个简单的文件下载。从MVC 5下载文件到Angular 2

我已经阅读了我在Stackoverflow上找到的所有示例,但我仍然没有得到我的示例工作。

在服务器端我有这样的C#代码:

public ActionResult DownloadPicture(long id) 
    { 
     var bytes = System.IO.File.ReadAllBytes("images\dummy.jpg"); 
     return GetAttachement(bytes, "DummyFile.jpg"); 
    } 

    private ActionResult GetAttachement(byte[] bytes, string fileName) 
    { 
     var contentType = MimeMapping.GetMimeMapping(fileName); 
     var contentDisposition = new System.Net.Mime.ContentDisposition 
     { 
      FileName = fileName, 
      Inline = true 
     }; 
     Response.AppendHeader("Content-Disposition", contentDisposition.ToString()); 
     return File(bytes, contentType); 
    } 

在客户端我有这样的打字稿代码:

public pictureDownload(id: number): void { 
    let options = new RequestOptions({ search: new URLSearchParams("id=" + id) }); 
    this.http.get(this.urlPictureDownload, options).subscribe((data: any) => { 
       // var blob = new Blob([data._body], { type: "image/jpeg" }); 
       // var url = window.URL.createObjectURL(blob); 
       // window.open(url); 
     }); 
} 

的请求进来到服务器端。阵列被下载。我想我的问题在于客户端。谁能帮我吗?

+1

有趣的 - 我没有[试过这个](https://templth.wordpress。com/2014/11/21/handle-downloads-with-angular /)与[FileSaver.js](https://github.com/eligrey/FileSaver.js)。请注意'arraybuffer'。 Hth ... – EdSF

+0

是否有一个原因,你不能只使用一个普通的旧链接的文件?这可能是最简单的。 – Casey

+0

我知道,我真的很想,但文件不在磁盘上。它们存储在后端存储中,所以我实际上将它们视为流。 –

回答

0

对于所有未来的读者,我总结一下这里。从建议EsDFpenearydevelopment建议我现在有一个工作解决方案。在请求中将responseType指定为ArrayBuffer是最关键的部分,下载技巧非常有用。

Alt 1:我认为凯西是对的。只要有可能,最简单的方法就是使用指向服务器资源的简单链接标记。和我一样,这不是一种选择,其他两种选择中的任何一种都是有用的。

Alt 2:openPictureInNewWindow方法是简单直接的方法。缺点是它会显示一个奇怪的URL,如下所示:blob:http://localhost/037713d1-a8b9-4fe3-8c43-ee5998ffdc5d

替代方法3:另一种方法downloadFile将更进一步,创建一个临时链接标记并利用它进行文件下载。对大多数用户来说,这看起来就像常规方法。但它不像使用“Angular 2方法”来操纵DOM,但它是一种更加用户友好的方式,所以现在我将使用它。感谢所有好的输入!

public pictureDownload(id: number) { 
    let options = new RequestOptions({ search: new URLSearchParams("id=" + id), responseType: ResponseContentType.ArrayBuffer }); 
    this.http.get(this.urlPictureDownload, options).subscribe((data: any) => { 
     //this.openPictureInNewWindow(data._body, "image/jpeg"); 
     this.downloadFile(data._body, "Screenshot_" + id + ".jpg", "image/jpeg"); 
    }); 
} 

private openPictureInNewWindow(data: ArrayBuffer, contentType: string) { 
    var blob = new Blob([data], { type: contentType }); 
    var url = window.URL.createObjectURL(blob); 
    window.open(url); 
} 

private downloadFile(data: ArrayBuffer, fileName: string, contentType: string) { 
    var blob = new Blob([data], { type: contentType }); 
    var url = window.URL.createObjectURL(blob); 

    var link = document.createElement("a"); 
    link.setAttribute("href", url); 
    link.setAttribute("download", fileName); 
    link.style.display = "none"; 
    document.body.appendChild(link); 
    link.click(); 
    document.body.removeChild(link); 
} 
+0

我在angular1中也遇到过困难。我确实从db获取了我的图像作为bytearray,通过webapi将它们作为json进行挖掘并将结果插入到img src标记中。 (工作)然而,这有问题,JSON变得相当大,没有发生客户端缓存。 (我使用这种方法来获取小图像,因此这个主题留待未来改进)。 – Nils

2

无论它的价值如何,这不仅仅是Angular2的一个问题。这似乎是浏览器(或可能是规范)的一个“问题”。我知道这种方法有几种不同的选择。

  1. 一旦字节组被返回给浏览器,你可以做这样的事情: var pom = document.createElement('a'); pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(data)); pom.setAttribute('download', 'PICTURENAME.jpeg'); pom.style.display = 'none'; document.body.appendChild(pom); pom.click(); document.body.removeChild(pom);

  2. 另一种方法我所知道的是,在一个临时路径来创建服务器上的文件和然后使用标识该文件的标识(通常为GUID)将重定向结果返回给用户,并将该路由重定向以返回文件结果。

1

如果您在浏览器中看到应用程序的后端网址中的图像,然后,您可以直接将它分配给img的src,如下所示:

假设您在组件中声明一个带有imgURL的字段,并使用后端映像操作方法初始化它。然后在标记你可以这样做

<img src='{{imgURL}}' alt='any message'/> 
+0

我大概已经对此更加具体了。我很想使用一个简单的URL,但这些文件不在磁盘上。它们存储在后端存储中,所以我实际上将它们视为流。 –