将文件从MVC 5下载到Angular 2

问题描述:

我有C#后端和ASP.Net MVC的经验.现在,我首次尝试使用Angular2.虽然需要时间,但我喜欢其中的大多数.现在,我只能进行简单的文件下载.

I have experience in C# backend and ASP.Net MVC. Now I am making my first attempt on Angular 2. It takes time but I like most of it. Now I am stuck on a simple file download.

我已经阅读了我在*上找到的所有示例,但是我仍然无法使用我的示例.

I have read all examples that i found here on *, but I still don't get my example to work.

在服务器端,我有以下C#代码:

On server side I have this C# code:

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

在客户端,我有以下打字稿代码:

On client side I have this Typescript code:

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

请求进入服务器端.阵列已下载.我想我的问题出在客户端.有人可以帮我吗?

The request is coming in to server side. The array is downloaded. I guess my problem lies on client side. Can anyone help me out?

对于所有将来的读者,我在这里总结一下.通过 EsDF 的建议和 peinearydevelopment 的建议,我现在有了一个可行的解决方案.在请求中将responseType指定为ArrayBuffer是最关键的部分,并且下载技巧确实很有帮助.

For all future readers I sum it all up here. By suggestion from EsDF with suggestion from peinearydevelopment I now have a working solution. Specifying the responseType as ArrayBuffer in the request was the most crucial part and the download trick was really helpful.

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

Alt 1: I think Casey is right. Whenever possible the easiest way is to just use a simple link tag that points to a server resource. When as in my case, that is not an option, any of the other two alternatives will be useful.

替代2:openPictureInNewWindow方法是一种简单明了的方法.缺点是它将显示一个如下所示的奇数网址:blob: http://localhost/037713d1-a8b9-4fe3-8c43-ee5998ffdc5d .

Alt 2: The method openPictureInNewWindow is the simple and straightforward approach. The downside is that it will present an odd url that looks like this: blob:http://localhost/037713d1-a8b9-4fe3-8c43-ee5998ffdc5d.

Alt 3:另一种方法downloadFile将更进一步,并创建一个临时链接标记,并将其用于文件下载.对于大多数用户而言,这看起来像是正常方法.但这并不像操纵DOM的"Angular 2方法",但是它是一种更加用户友好的方法,所以现在我将使用这种方法.感谢您的所有宝贵意见!

Alt 3: The other method downloadFile will go one step further and create a temporary link tag and make use of it for file download. That will for most users look like the normal approach. But it doesn't feel like an "Angular 2 approach" manipulating the DOM, but it is a more user friendly way, so for now that is the one I will use. Thanks for all good input!

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