Search code examples
javascriptc#asp.netpdf

MemoryStream to HttpResponseMessage


I have generated a Pdf on the server, and need to return it as a response to my web client, so that I get a 'Save As' dialog.

The pdf is generated, and saved to a Memory stream... which is then returned to my method which will return the HttpResponseMessage.

The is the method:

[Route("GeneratePdf"), HttpPost]
public HttpResponseMessage GeneratePdf(PlateTemplateExtendedDto data)
{

    var doc = GeneratePdf(DataForThePdf);

    //using (var file = File.OpenWrite("c:\\temp\\test.pdf"))
    //    doc.CopyTo(file); // no need for manual stream copy and buffers

    HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);

    byte[] buffer = new byte[0];
    //get buffer
    buffer = doc.GetBuffer();
    //content length for use in header
    var contentLength = buffer.Length;

    response.Headers.AcceptRanges.Add("bytes");
    response.StatusCode = HttpStatusCode.OK;
    response.Content = new StreamContent(doc);
    response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("render");
    response.Content.Headers.ContentDisposition.FileName = "yes.pdf";
    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
    response.Content.Headers.ContentLength = doc.Length;

    return response;
}

However, the document renders as a blank file, and although it has a file size, and properties of the document I created (pdf information if File Properties is all right, as well as page width and height), the document displays as blank.

If I un-comment the code that is commented out, to save locally, the file is perfect. File size is 228,889 bytes. However, when I let it go to my web page and save it, it's 405,153 bytes and the filename is 'undefined'.

If I breakpoint, I see these results:

enter image description here

On the front end script, I handle the downloaded object like this:

$.post("/api/PlateTemplate/GeneratePdf", data).done(function (data, status, headers) {

            // headers = headers();

            var filename = headers['x-filename'];
            var contentType = headers['content-type'];
            //Create a url to the blob
            var blob = new Blob([data], { type: contentType });
            var url = window.URL.createObjectURL(blob);
            var linkElement = document.createElement('a');
            linkElement.setAttribute('href', url);
            linkElement.setAttribute("download", filename);

            //Force a download
            var clickEvent = new MouseEvent("click", {
                "view": window,
                "bubbles": true,
                "cancelable": false
            });
            linkElement.dispatchEvent(clickEvent);
        });

I'm unsure where the file is being corrupted. What am I doing wrong?

Edit: Using the following code as suggested:

$.post("/api/PlateTemplate/GeneratePdf", data).done(function (data, status, headers) {
            alert(data.length);

            var xhr = new XMLHttpRequest();

            $("#pdfviewer").attr("src", URL.createObjectURL(new Blob([data], {
                type: "application/pdf"
            })))

.Net code:

var doc = GeneratePdf(pdfParams);

            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);

            byte[] buffer = new byte[0];
            //get buffer
            buffer = doc.ToArray();
            //content length for use in header
            var contentLength = buffer.Length;

            response.Headers.AcceptRanges.Add("bytes");
            response.StatusCode = HttpStatusCode.OK;
            response.Content = new StreamContent(doc);
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("render");
            response.Content.Headers.ContentDisposition.FileName = "yes.pdf";
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
            response.Content.Headers.ContentLength = doc.Length;

            return response;

It seems I am losing data. The alert is the length of the 'data.length' in my javascript, after I get data back from the call. The file properties is the original pdf file info.

enter image description here

File sends from api, size is 227,564, which matches the byte size on disk if I save it. So it SEEMS the sending is OK. But on the javascript size, when I read in the file, it's 424946, when I do: var file = new Blob([data], { type: 'application/pdf' }); (Where data is the response from the server).


Solution

  • I 'fixed' this by using base64 encoded string from the .Net controller to the javascript web api call result, and then allowed the browser to convert it into binary by specifying the type ('application/pdf').