Base64 conversion for any Attachment

PrakshalJain
Tera Contributor

Hi Friends,

I have a use case where I need to send an MMS message to a phone number. I learned that any attachment must be converted into Base64 format.

I am using an SMS service 'sndryt' endpoint that requires an API key along with mandatory parameters such as the message, phone number, business unique ID, and organization ID.(I have all with me)

To test the compatibility of the endpoint for handling MMS, I manually converted an image to Base64 using an online converter and passed it as a parameter in Postman. The recipient successfully received the message with the image.

Now, I am trying to achieve the same in ServiceNow via Flow Designer. I have attached an image to an incident record, retrieved its sys_id from the sys_attachment table, and am passing it as input.
I have created a custom action

PrakshalJain_0-1738935666030.png

passing attachment sys_id, phone, b_uid, org_id, message as an input

Below is the next script step I am using:
Script:

(function execute(inputs, outputs) {
    gs.info('Fetching attachment for Sys ID: ' + inputs.attachment_sys_id);

    // Validate inputs
    if (!inputs.attachment_sys_id || inputs.attachment_sys_id.trim() === "" ||
        !inputs.phone_number || inputs.phone_number.trim() === "" ||
        !inputs.message || inputs.message.trim() === "" ||
        !inputs.business_unit_id || inputs.business_unit_id.trim() === "" ||
        !inputs.org_id || inputs.org_id.trim() === "") {

        gs.error('Missing required inputs.');
        outputs.http_response_status = 400;
        outputs.http_response_body = "ERROR: Missing required inputs.";
        return;
    }

    // Retrieve the attachment record
    var attachmentGR = new GlideRecord('sys_attachment');
    if (!attachmentGR.get(inputs.attachment_sys_id)) {
        gs.error('Attachment not found for sys_id: ' + inputs.attachment_sys_id);
        outputs.http_response_status = 404;
        outputs.http_response_body = "ERROR: Attachment not found.";
        return;
    }

    // Retrieve metadata
    var fileName = attachmentGR.getValue('file_name');
    var mimeType = attachmentGR.getValue('content_type');
    var attachmentSize = attachmentGR.getValue('size_bytes');

    gs.info('Attachment Found: ' + fileName);
    gs.info('Size (Bytes): ' + attachmentSize);
    gs.info('MIME Type: ' + mimeType);

    // Ensure only valid image MIME types are sent
    var allowedMimeTypes = ["image/png", "image/jpeg", "image/gif"];
    if (!allowedMimeTypes.includes(mimeType)) {
        gs.error('Invalid attachment type. Only PNG, JPEG, and GIF are supported.');
        outputs.http_response_status = 415; // Unsupported Media Type
        outputs.http_response_body = "ERROR: Only PNG, JPEG, and GIF images are allowed.";
        return;
    }

    try {
        // Retrieve the attachment content as a byte array
        var attachmentUtil = new GlideSysAttachment();
        var attachmentData = attachmentUtil.getBytes('sys_attachment', inputs.attachment_sys_id);

        // Ensure attachment data is valid
        if (!attachmentData || attachmentData.length === 0) {
            gs.error('Error: Unable to retrieve attachment data.');
            outputs.http_response_status = 500;
            outputs.http_response_body = "ERROR: Unable to retrieve attachment data.";
            return;
        }

        gs.info('Successfully retrieved attachment bytes. Encoding to Base64...');

        // Convert byte array to a JavaScript-compatible string before encoding
        var binaryString = "";
        for (var i = 0; i < attachmentData.length; i++) {
            binaryString += String.fromCharCode(attachmentData[i] & 0xFF);
        }

        var base64Encoded = GlideStringUtil.base64Encode(binaryString);

        if (!base64Encoded || base64Encoded.length === 0) {
            gs.error('Error: Base64 encoding failed.');
            outputs.http_response_status = 500;
            outputs.http_response_body = "ERROR: Base64 encoding failed.";
            return;
        }

        gs.info('Base64 Encoding Successful! Length: ' + base64Encoded.length);

        // Construct the payload dynamically
        var payload = {
            org_id: inputs.org_id,
            business_unit_id: inputs.business_unit_id,
            api_key: "<API Key>", // Hardcoded API Key (have that with me)
            phone_number: inputs.phone_number,
            message: inputs.message,
            media: "data:" + mimeType + ";base64," + base64Encoded.trim() // Trim to avoid unnecessary spaces
        };

        gs.info('Payload Constructed: ' + JSON.stringify(payload));

        // REST API Request
        var request = new sn_ws.RESTMessageV2();
        request.setHttpMethod('POST');
        request.setEndpoint('https://ap.sndright.com/api/SndDirect/');
        request.setRequestHeader('Content-Type', 'application/json');
        request.setRequestHeader('Accept', 'application/json');
        request.setRequestBody(JSON.stringify(payload));

        // Execute the request
        var response = request.execute();
        var httpResponseStatus = response.getStatusCode();
        var responseBody = response.getBody();

        gs.info('HTTP Response Status Code: ' + httpResponseStatus);
        gs.info('HTTP Response Body: ' + responseBody);

        outputs.http_response_status = httpResponseStatus;
        outputs.http_response_body = responseBody;
    } catch (ex) {
        gs.error('Error processing attachment: ' + (ex.getMessage() || ex));
        outputs.http_response_status = 500;
        outputs.http_response_body = "ERROR: Exception while processing attachment.";
    }
})(inputs, outputs);

 

PrakshalJain_1-1738935822074.png

 

I place log info for debugging

PrakshalJain_2-1738935957454.png

 


Failing at this
"Error processing attachment: TypeError: Cannot find default value for object."
till then able to process everything getting meta data of the attachment
Facing issues with conversion.

Anyone Please Help




9 REPLIES 9

@PrakshalJain 

Code I shared will give the base64 encoded data if you have attachment record sysId

There seems some other error

what debugging have you done so far?

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

@PrakshalJain 

add gs.info() to debug at correct places because script I shared will work fine to get base64 data

If my response helped please mark it correct and close the thread so that it benefits future readers.

 

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

Hi Ankur,

I tried your above method as well
Now I am trying to get Base64 content in Background script

Below is the script:

function getAttachmentBase64(attachmentSysId) {
    if (!attachmentSysId || attachmentSysId.trim() === '') {
        gs.error(' ERROR: Invalid attachmentSysId provided.');
        return null;
    }

    var attachmentGR = new GlideRecord('sys_attachment');
    if (!attachmentGR.get(attachmentSysId)) {
        gs.error(' ERROR: Attachment not found for Sys ID: ' + attachmentSysId);
        return null;
    }

    var fileName = attachmentGR.getValue('file_name');
    var contentType = attachmentGR.getValue('content_type');

    gs.info('📂 Fetching Attachment: ' + fileName + ' (MIME: ' + contentType + ')');

    try {
        var gsis = new GlideSysAttachmentInputStream(attachmentGR.getUniqueValue());
        var byteArrayOutputStream = new Packages.java.io.ByteArrayOutputStream();
       
        gsis.writeTo(byteArrayOutputStream, 0, 0);
        byteArrayOutputStream.close();

        var base64EncodedContent = GlideStringUtil.base64Encode(byteArrayOutputStream.toByteArray());

        if (!base64EncodedContent || base64EncodedContent.trim() === '') {
            gs.error(' ERROR: Base64 encoding failed.');
            return null;
        }

        gs.info(' Successfully converted to Base64. Length: ' + base64EncodedContent.length);
        return base64EncodedContent;

    } catch (error) {
        gs.error(' ERROR: Exception while processing attachment: ' + error);
        return null;
    }
}

// Example usage:
var attachmentSysId = '882828469327d610898bf84958373c2c'; // Replace with actual sys_id
var base64Attachment = getAttachmentBase64(attachmentSysId);

if (base64Attachment) {
    gs.info('🔹 Base64 Content (First 100 chars): ' + base64Attachment.substring(0, 100) + '...');
}

Error and logs:
*** Script: 📂 Fetching Attachment: image.jpg (MIME: image/jpeg)
*** Script: ERROR: Exception while processing attachment: TypeError: Cannot find default value for object.: no thrown error



Also trying on my own
Below Script:

function getAttachmentBase64(attachmentSysId) {
    if (!attachmentSysId || attachmentSysId.trim() === '') {
        gs.error(' ERROR: Invalid attachmentSysId provided.');
        return null;
    }

    var attachmentGR = new GlideRecord('sys_attachment');
    if (!attachmentGR.get(attachmentSysId)) {
        gs.error(' ERROR: Attachment not found for Sys ID: ' + attachmentSysId);
        return null;
    }

    var fileName = attachmentGR.getValue('file_name');
    var contentType = attachmentGR.getValue('content_type');

    gs.info('📂 Fetching Attachment: ' + fileName + ' (MIME: ' + contentType + ')');

    try {
        var attachmentUtil = new GlideSysAttachment();
        var attachmentBytes = attachmentUtil.getBytes(attachmentGR);

        if (!attachmentBytes || attachmentBytes.length === 0) {
            gs.error(' ERROR: Failed to retrieve attachment bytes.');
            return null;
        }

        gs.info(' Successfully retrieved attachment bytes. Encoding to Base64...');
        var base64EncodedContent = GlideStringUtil.base64Encode(attachmentBytes);

        if (!base64EncodedContent || base64EncodedContent.trim() === '') {
            gs.error(' ERROR: Base64 encoding failed.');
            return null;
        }

        gs.info(' Successfully converted to Base64. Length: ' + base64EncodedContent.length);
        return base64EncodedContent;

    } catch (error) {
        gs.error(' ERROR: Exception while processing attachment: ' + error);
        return null;
    }
}

// Example usage:
var attachmentSysId = '882828469327d610898bf84958373c2c'; // Replace with actual sys_id
var base64Attachment = getAttachmentBase64(attachmentSysId);

if (base64Attachment) {
    gs.info('🔹 Base64 Content (First 100 chars): ' + base64Attachment.substring(0, 100) + '...');
}

Repeated Error:
*** Script: 📂 Fetching Attachment: image.jpg (MIME: image/jpeg)
*** Script: Successfully retrieved attachment bytes. Encoding to Base64...
*** Script: ERROR: Exception while processing attachment: TypeError: Cannot find default value for object.: no thrown error

@PrakshalJain 

I did help you on getting the base64 data of file.

Further debugging you can perform.

Seems issue with your other script part.

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader