将文件从MVC 5下载到Angular 2

时间:2017-02-01 16:13:18

标签: c# asp.net asp.net-mvc angular

我有C#后端和ASP.Net MVC的经验。现在我正在第一次尝试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);
    }

在客户端,我有这个Typescript代码:

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);
       });
 }

请求进入服务器端。该阵列已下载。我猜我的问题出在客户端。任何人都可以帮助我吗?

3 个答案:

答案 0 :(得分:2)

无论它的价值如何,这都不是Angular2的问题。这似乎是一个问题'使用浏览器(或可能是规范)。您可以通过这种方法了解一些不同的选项。

  1. 将bytearray返回给浏览器后,您可以执行以下操作: 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. 我所知道的另一种方法是在临时路径上在服务器上创建文件,然后将重定向结果返回给具有标识该文件的id的用户(通常是GUID)和将该路由重定向以返回您的文件结果。

答案 1 :(得分:1)

如果您在浏览器中看到了应用后端网址的图片。然后你可以直接将它分配给组件标记中的img的src,如下所示:

假设您在组件中声明了一个包含imgURL的字段,并使用您的后端图像操作方法对其进行初始化。然后在标记中你可以这样做

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

答案 2 :(得分:1)

对于所有未来的读者,我在这里总结一下。根据 EsDF 的建议以及来自 peinearydevelopment 的建议,我现在有了一个有效的解决方案。在请求中将responseType指定为ArrayBuffer是最关键的部分,下载技巧非常有用。

替补1:我认为凯西是对的。只要有可能,最简单的方法是使用指向服务器资源的简单链接标记。在我的情况下,这不是一个选项,其他两个选择中的任何一个都是有用的。

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

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

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);
}