1

I need to use JQuery ajax to post a complex and sensitive data object (nested objects, arrays, and Personally Identifiable Information) to my server, where a PDF is generated and returned to the client. The client browser then should open the PDF in a new window.

Because of the nature of the data the request neither can nor should be an encoded URL - it must include the data as a JSON body.

The other questions/answers on this subject did not solve the problem in my case or do not do so completely.

Groppe
  • 3,819
  • 12
  • 44
  • 68
  • See also [How to build PDF file from binary string returned from a web-service using javascript](http://stackoverflow.com/questions/12876000/how-to-build-pdf-file-from-binary-string-returned-from-a-web-service-using-javas/), [jquery-ajax-blob-arraybuffer.js](https://gist.github.com/SaneMethod/7548768) – guest271314 Dec 30 '16 at 05:43

1 Answers1

4

Solution

  1. POST with the data in the body as JSON.
  2. Set the expected Content-Type of the response to arraybuffer (on the client and server).
  3. When the request has complete successfully, convert the response to a Blob.
  4. Create an object url to the Blob and open it in a new window.

Notes

  • JQuery ajax does not support the arraybuffer Content-Type so the base JavaScript xhr must be used (if you don't have any other options).
  • Internet Explorer has its own functionality for handling and displaying Blob's, so a special case is needed.
  • Supported browsers does not include IE9

Code

RequestPdf = function (url, data) {
    var request = new XMLHttpRequest(), file, fileURL;
    request.open("POST", url);
    request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
    request.responseType = "arraybuffer";
    request.send(data);
    request.onreadystatechange = function () {
        if (request.readyState === 4 && request.status === 200) {
            file = new Blob([request.response], { type: 'application/pdf' });
            if (window.navigator && window.navigator.msSaveOrOpenBlob) { // IE
                window.navigator.msSaveOrOpenBlob(file);
            } else {
                fileURL = URL.createObjectURL(file);
                window.open(fileURL);
            }
        }
    };
};
Groppe
  • 3,819
  • 12
  • 44
  • 68
  • What is purpose of setting `.responseType` to `"arraybuffer"` where `ArrayBuffer` is then converted to `Blob`? – guest271314 Dec 30 '16 at 05:12
  • 1
    `createObjectUrl` only takes a `Blob` (or a `File`) as an input parameter. https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL – Groppe Jan 04 '17 at 20:06
  • 1
    _"where a PDF is generated and returned to the client"_ If server reponds with `content-type:application/pdf` header `.responseType = "blob"` could be used? Does response not have `content-type:application/pdf` header set? – guest271314 Jan 04 '17 at 22:13
  • the response actually has `content-type:arraybuffer` set. I have not tried to set it directly to `blob`, though. Your suggestion might be a more direct solution to that aspect of the problem. – Groppe Jan 05 '17 at 19:33