The CreatorCon Call for Content is officially open! Get started here.

Sending a pdf to the Rest API with javascript

pacherault
Giga Contributor

Hello,

I'm trying to send a PDF file to ServiceNow through the Rest API but all the sent PDF are blank when opened at ServiceNow side.

Here are the details of what I'm trying to do.

From my tools on the web browser, I download the PDF from the server and I obtain it as the base64 encoded string.

The API I'm contacting is : Attachement API - POST /now/attachement/file

https://docs.servicenow.com/bundle/istanbul-servicenow-platform/page/integrate/inbound-rest/referenc...

What I tried to do :

var data = new FormData();

data.append(file_name, atob(file64));// decode from base64 to string

//Start request

$.ajax(

{

        url: base_url + "/api/nom/attachment/file?table_name=incident&table_sys_id=" + sys_id + "&file_name=" + file_name,

        type: "POST",

        dataType: "json",

        data: data,

        beforeSend: function(xhr)

        {

                  xhr.setRequestHeader("Authorization", "Bearer " + token);

                  xhr.setRequestHeader("Content-Type", "application/pdf");

        },

        success: function(data)

        {

                  alert("Success");

        },

        error: function(result)

        {

                  alert("Error : " + result);

        },

});

That's more or less the code I'm using to send the file to ServiceNow and I got a positive answer on that one : 201 Created.

But when my interlocutor tries to open the file, the PDF is completely blank and on closure the PDF reader ask to save the file. After saving, the document is still blank.

Opening the file with a text editor shows Boundary limits, as if the server didn't removed them after receiving the file.

------WebKitFormBoundaryIffgXSqZrXwI7Ysx

Content-Disposition: form-data; name="Test1.pdf"

I also tried to send the file without a form data.

var data = atob(file64));// decode from base64 to string

//Start request

$.ajax(

{

        url: base_url + "/api/nom/attachment/file?table_name=incident&table_sys_id=" + sys_id + "&file_name=" + file_name,

        type: "POST",

        dataType: "json",

        data: data,

        beforeSend: function(xhr)

        {

                  xhr.setRequestHeader("Authorization", "Bearer " + token);

                  xhr.setRequestHeader("Content-Type", "application/pdf");

        },

        success: function(data)

        {

                  alert("Success");

        },

        error: function(result)

        {

});

                  alert("Error : " + result);

        },

});

But I got the same result, PDF blank asking for save. This time without Bondary limits (logical as didn't use FormData() ) ...

I also tried to send the base64 encoded string specifying in the HTTP request that it was encoded.

xhr.setRequestHeader("Content-Type", "application/pdf; base64");

I got less success this time, as the string wasn't decoded by the server and still saved as a PDF.

Am I doing something wrong in sending the file to ServiceNow ? Does anyone have an hint on how to solve this ?

Regards,

1 ACCEPTED SOLUTION

pacherault
Giga Contributor

Hello,



I more or less founded an answer to my problem. As PDF files seem to be binary files, there is a specific way to handle them, which I knew nothing about.



To successfully send a pdf files with ajax, you need to use a BLOB (Binary Large OBject), as described here : Sending and Receiving Binary Data - Web APIs | MDN (part Sending binary data)


More info on those BLOB can be found here : Blob() - Web APIs | MDN



The solution to my problem come from this post : Creating a Blob from a base64 string in JavaScript - Stack Overflow



For those who might need it, here is the code I implemented :



var file64 = "";// get base64 encoded file



// Start Request


var xhr = new XMLHttpRequest();


xhr.open("POST", base_url + "/api/now/attachment/file?table_name=incident&table_sys_id=" + sys_id + "&file_name=" + file_name);


xhr.setRequestHeader("Content-Type", "application/pdf");


xhr.setRequestHeader("Authorization", "Bearer " + token);



xhr.onreadystatechange = function(response)


{


        if (this.readyState === XMLHttpRequest.DONE)// Get the Http status from ServiceNow's server


        {


                  alert(this.status + " " + this.statusText);


        }


}



// Transform the base64 encoded file into a Blob


var byteCharacters = atob(file64);


var byteArrays= [];


var sliceSize = 512;



for (var offset = 0; offset < byteCharacters.length; offset += sliceSize)


{


        var slice = byteCharacters.slice(offset, offset + sliceSize);


        var byteNumbers = new Array(slice.length);


        for (var i = 0; i < slice.length; i++)


        {


                  byteNumbers[i] = slice.charCodeAt(i);


        }


        var byteArray = new Uint8Array(byteNumbers);



        byteArrays.push(byteArray);


}



var blob = new Blob(byteArrays, {type: "application/pdf",});


xhr.send(blob);// Add the blob to the request and send it



PDF files are successfully sent to, saved on server and read by users.


View solution in original post

4 REPLIES 4

Manville
Mega Guru

Hello Francois,



Is the PDF file in the binary format? Did you decode the file into Binary?



Jeff


Hello Jeffrey,



If I recall correctly, PDF files are binary files already, so I'm not sure I understand what you mean by decoding the file into binary ...


pacherault
Giga Contributor

Hello,



I more or less founded an answer to my problem. As PDF files seem to be binary files, there is a specific way to handle them, which I knew nothing about.



To successfully send a pdf files with ajax, you need to use a BLOB (Binary Large OBject), as described here : Sending and Receiving Binary Data - Web APIs | MDN (part Sending binary data)


More info on those BLOB can be found here : Blob() - Web APIs | MDN



The solution to my problem come from this post : Creating a Blob from a base64 string in JavaScript - Stack Overflow



For those who might need it, here is the code I implemented :



var file64 = "";// get base64 encoded file



// Start Request


var xhr = new XMLHttpRequest();


xhr.open("POST", base_url + "/api/now/attachment/file?table_name=incident&table_sys_id=" + sys_id + "&file_name=" + file_name);


xhr.setRequestHeader("Content-Type", "application/pdf");


xhr.setRequestHeader("Authorization", "Bearer " + token);



xhr.onreadystatechange = function(response)


{


        if (this.readyState === XMLHttpRequest.DONE)// Get the Http status from ServiceNow's server


        {


                  alert(this.status + " " + this.statusText);


        }


}



// Transform the base64 encoded file into a Blob


var byteCharacters = atob(file64);


var byteArrays= [];


var sliceSize = 512;



for (var offset = 0; offset < byteCharacters.length; offset += sliceSize)


{


        var slice = byteCharacters.slice(offset, offset + sliceSize);


        var byteNumbers = new Array(slice.length);


        for (var i = 0; i < slice.length; i++)


        {


                  byteNumbers[i] = slice.charCodeAt(i);


        }


        var byteArray = new Uint8Array(byteNumbers);



        byteArrays.push(byteArray);


}



var blob = new Blob(byteArrays, {type: "application/pdf",});


xhr.send(blob);// Add the blob to the request and send it



PDF files are successfully sent to, saved on server and read by users.


Devendher
ServiceNow Employee
ServiceNow Employee

Hi ,

How can we convert Base64 string to Blob through servicenow script ?  Uint8Array and ArrayBuffer , Blob key words ( functionality of ES6) not supported while running through servicenow script, Does it work for you ?