1

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 Answer 1

3

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");
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. Finally It works now. You saved days of my time. From your idea, I researched a bit about base64 and followed the link link. Now it works in your method as well as just in normal byte[] format from API.
@Aussie That's consider. Consider accepting the answer if it is helpful.
I'd like to accept your answer but because my reputation rate, I don't seem to have an option to do it.
@Aussie See the grey checkmark on left, under the answer's upvotes/downvotes. Thank you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.