1
votes

My Angular project cannot download (for Save as) a pdf file via ASP.NET core Api. The pdf file is stored in SQL server.

I tried a number of ways posted in stackoverflow but none of the ones works for me. Some examples download a pdf file but if It was tried to open, It caught an error '..not support...damaged'.

API (I perfer returning a row instead of a single vaule byte[] only)

[HttpGet]
        [Route("detail/{studentid:int}/{reportSeq:int}")]
        public async Task<ActionResult<byte[]>> GetStudentAcademicReport2(int StudentID, int ReportSeq)
        {            
            var report = await _context.AcademicReportDetails.FromSql("select * from [dbo].[ufnStudentAcademicReport] (8213, 8158)").FirstOrDefaultAsync();
            if (report == null)
            {
                return NotFound();
            }
            return report.ReportContent;
        }
  1. Not working in Angular

this.httpClient.get("https://localhost:44369/api/values/detail/8213/8158", { responseType: 'blob'})
.subscribe(response => { console.log(response);

  const url = window.URL.createObjectURL(new Blob([response]));
  const link = document.createElement('a');
  link.href = url;
  link.setAttribute('download', 'file.pdf');
  document.body.appendChild(link);
  link.click();
  1. Not working in Angula

    this.httpClient.get("http://localhost:5000/api/studentacademicreports/detail/8213/8158", { responseType: 'arraybuffer'})
    .subscribe(response => { console.log(response);

      const file = new Blob([response], {type: 'application/pdf'});
      const fileURL = window.URL.createObjectURL(file);
    
      let objectURL = 'data:image/jpeg;base64,' +  response;
      let fileURL2 = this.sanitizer.bypassSecurityTrustUrl(objectURL); 
    
      const link = document.createElement('a');
      link.href = fileURL;
      link.download = 'sample.pdf';
      link.click();
    
  2. Working in Windows form project

    cmd.CommandText = "select * from [dbo].[ufnStudentAcademicReport] (8213, 8158)"; cmd.CommandType = CommandType.Text;

                    if (cmd.Connection.State != ConnectionState.Open)
                    {
                        cmd.Connection.Open();
                    }
    
                    DbDataReader read = cmd.ExecuteReader();
                    if (read.HasRows)
                    {
                        while (read.Read())
                        {
                            byte[] b = null;                                
                            b = (byte[])read.GetValue(read.GetOrdinal("ReportContent"));
                            System.IO.File.WriteAllBytes(@"c:\temp\test.pdf", b);    
                        }    
                    }
    
  3. Not working in Windows form project via API

HttpClient http = new HttpClient(); var NewResponse = await http.GetAsync("https://localhost:44369/api/values/detail/8213/8158");

        var content = await NewResponse.Content.ReadAsByteArrayAsync();

        System.IO.File.WriteAllBytes(@"c:\temp\test111.pdf", content);

As you can see from my above sample codes that it works if a pdf in varbinary(Max) is downloaded directly using SQLCommand but doesn't work if a pdf is downloaded via API. I am suspecting that API returns byte[] in Json format. Student photos are displayed successfully via the api without any issue but downloading Pdf file doesn't work. What causes downloaded PDF files corrupted in my codes?

1

1 Answers

3
votes

When you return byte[] from ASP.NET Core action it's result is base64 encoded and that's why you get a "corrupted" file. You have to return FileResult from action in order to let the framework process binary data properly

public async Task<FileResult> GetStudentAcademicReport2(int StudentID, int ReportSeq)
{
    var report = await _context.AcademicReportDetails.FromSql("select * from [dbo].[ufnStudentAcademicReport] (8213, 8158)").FirstOrDefaultAsync();
    if (report == null)
    {
        return NotFound();
    }
    return File(report.ReportContent, "application/pdf", "test.pdf");
}