Search code examples
c#angularjsasp.net-web-apiasp.net-web-api2memorystream

Angular/Web API 2 returns invalid or corrupt file with StreamContent or ByteArrayContent


I'm trying to return a file in a ASP.NET Web API Controller. This file is a dynamically-generated PDF saved in a MemoryStream.

The client (browser) receives the file successfully, but when I open the file, I see that all the pages are totally blank.

The thing is that if I take the same MemoryStream and write it to a file, this disk file is displayed correctly, so I assume that the problem is related to the file transfer via Web.

My controller looks like this:

[HttpGet][Route("export/pdf")]
public HttpResponseMessage ExportAsPdf()
{
    MemoryStream memStream = new MemoryStream();
    PdfExporter.Instance.Generate(memStream);

    memStream.Position = 0;
    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
    result.Content = new ByteArrayContent(memStream.ToArray()); //OR: new StreamContent(memStream);
    return result;
}

Just to try, if I write the stream to disk, it's displayed correctly:

[HttpGet][Route("export/pdf")]
public HttpResponseMessage ExportAsPdf()
{
    MemoryStream memStream = new MemoryStream();
    PdfExporter.Instance.Generate(memStream);

    memStream.Position = 0;
    using (var fs = new FileStream("C:\\Temp\\test.pdf", FileMode.OpenOrCreate, FileAccess.ReadWrite))
    {
        memStream.CopyTo(fs);
    }

    return null;
}

The differences are:

  • PDF saved on disk: 34KB
  • PDF transferred via web: 60KB (!)

If I compare both files contents, the main differences are:

File Differences

On the left is the PDF transferred via web; on the right, the PDF saved to disk.

Is there something wrong with my code? Maybe something related to encodings?

Thanks!


Solution

  • Well, it turned out to be a client (browser) problem, not a server problem. I'm using AngularJS in the frontend, so when the respose was received, Angular automatically converted it to a Javascript string. In that conversion, the binary contents of the file were somehow altered...

    Basically it was solved by telling Angular not to convert the response to a string:

    $http.get(url, { responseType: 'arraybuffer' })
    .then(function(response) {
        var dataBlob = new Blob([response.data], { type: 'application/pdf'});
        FileSaver.saveAs(dataBlob, 'myFile.pdf');
    });
    

    And then saving the response as a file, helped by the Angular File Saver service.