简体   繁体   中英

Angular can't download files from the .Net Core API

I'm using Angular 6 to download .docx files from the .Net Core 2.1 API.

The code of .Net Core below can directly get the .docx file through an URL in the browser after publishing to IIS.

This is the link I used to troubleshoot, so I don't think .Net Core is wrong:
Return file in ASP.Net Core Web API

When I use HttpClient to call the API in Angular, the body will be empty in the response...

.Net Core Controller

[HttpGet("[action]")]
public IActionResult DemoWordGet(string Custom, string Variety, string Type,
            string Brand, string ProductName, string Company = "test",
            string BeginDate = "2019-5-21", string EndDate = "2019-5-22")
{
    string DemoFile = _hostingEnvironment.ContentRootPath + @"\Templates\demo.docx";
    byte[] byteArray = System.IO.File.ReadAllBytes(DemoFile);
    MemoryStream memoryStream = new MemoryStream();

    memoryStream.Write(byteArray, 0, byteArray.Length);

    WordprocessingDocument document = WordprocessingDocument.Open(memoryStream, true);

    Body body = document.MainDocumentPart.Document.Body;

    Paragraph paragraph = body.AppendChild(new Paragraph());

    DocumentFormat.OpenXml.Wordprocessing.Run run = paragraph.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Run());
    run.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Text("it is test context!"));
    document.Close();

    string FileName = "test-" + DateTime.Now.ToString("yyyyMMdd") + ".docx";
    memoryStream.Seek(0, SeekOrigin.Begin);

    return File(memoryStream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", FileName);
}

Angular Component

this._printService.GetWord(printInfo).subscribe((response:any) => {
    const filename = response.headers.get('Content-Disposition').split(/[;'=]/).pop();
    saveAs(response.body, decodeURIComponent(filename))
});

Angular API Service

GetWord(params: HttpParams): Observable<any> {
    return this.http.get<Blob>(
            `${this.apiUrl}/DemoWordGet`, 
            {   
                params,
                responseType: 'blob' as 'json',
                observe: 'response',
            });
}

The request and response were shown fine in the browser, however the subscribed response in console.log() shows nothing...

https://imgur.com/a/VA04qiE

the chrome version: 74.0.3729.157

----- Update -----

  1. I enter the debug mode and discover that the response body will be empty until the subscription complete!!!

  2. The same problem is in Microsoft Edge as well.

  3. I can successfully download file by using the code below:

async test() {
    let res = await fetch(`${this.apiUrl}/DemoWordGet`, {
        method: 'GET',
        headers: {
            'Content-Type': 'application/octet-stream',
        }
    });

    res.blob().then(x => {
        saveAs(x, 'test.docx');
    });
}

Is this a bug about HttpClient??

I still have no idea what am I doing wrong in Angular?

You are converting your blob to json which is wrong so your code must change from this

responseType: 'blob' as 'json'

to this

responseType: "blob"

And you should use createObjectUrl to download the file something like this

downloadFile(data: Response) {
  const blob = new Blob([data], { type: 'text/csv' });
  const url= window.URL.createObjectURL(blob);
  window.open(url);
}
 return this.http
    .get(`${this.apiUrl}/DemoWordGet`, {
      responseType: ResponseContentType.Blob
    })
    .map(res => {
      return {
        filename: 'filename.pdf',
        data: res.blob()
      };
    });

This should be the way to set your content-type to mould it to a blob

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM