Saving RESTMessageV2 Responses as Attachments in ServiceNow

Applies to: Geneva, Helsinki and beyond.

Have you ever needed to:

  1. Retrieve something using RESTMessageV2
  2. Save that thing as an attachment on a record
  3. Do something with the newly generated attachment?

This recently came up as a question over in the sndevs slack channel, and I realized that I knew how to accomplish #1 and #2, but didn't know how to actually identify the attachment to achieve #3 without some ugly hacks. But as it turns out, there's a right way to do this.

First, some code

Here's a quick refresher on steps 1 and 2: retrieving and saving an attachment.

// This is where we'll save the attachment
var tablename   = 'incident';  
var recordSysId = '8d6353eac0a8016400d8a125ca14fc1f';  
var filename    = 'snlogo.png';

// Let's download the ServiceNow Logo
var logoUrl = 'https://instance.service-now.com/images/logos/logo_service-now.png';  
var request = new sn_ws.RESTMessageV2();  
request.setHttpMethod('get');  
request.setEndpoint(logoUrl);

// Configure the request to save the response as an attachment
request.saveResponseBodyAsAttachment(tablename, recordSysId, filename);

// When we execute the request, the attachment will automatically be
// saved to the record we specified
var response = request.execute();  
var httpResponseStatus = response.getStatusCode();  
var httpResponseContentType = response.getHeader('Content-Type');  
gs.debug("http response status_code: " + httpResponseStatus);  
gs.debug("http response content-type: " + httpResponseContentType);  

Now what?

If all you're concerned about is saving the attachment data to a record, you're done. No further actions are necessary. But what if you want to do something else with the attachment you just generated? Copy it somewhere, process its contents, etc?

The call to saveResponseBodyAsAttachment() returns void, so we can't get a reference to the attachment from there. We could do something super ugly like go query the sys_attachment table and find the latest attachment associated with our target record, but this is far from ideal and prone to bugs.

I was happy to learn that there's a correct way to do this.

Using getResponseAttachmentSysid()

The response object returned by request.execute() provides a method called getResponseAttachmentSysid(). As the method name suggests, this returns the sys_id of the attachment generated by the REST call.

To use this, we simply call the method after executing the request. We can append the following lines of code to the earlier example:

// Get the sys_id of the newly created attachment
var newAttachmentSysId = response.getResponseAttachmentSysid();

// Do something useful with it
var grAttach = new GlideRecord('sys_attachment');  
if (grAttach.get(newAttachmentSysId)) {  
  // Note: we're using the scoped version of GlideSysAttachment 
  // for this example. 
  var gsa = new GlideSysAttachment()
  var content = gsa.getContent(grAttach); 
  // Now we have the data...the rest is up to you
}

You can view/download the complete script here. This can be executed from Scripts - Background, just remember to update the instance URL and target table/record.

Happy attaching!

View and discuss this article on the ServiceNow Community.

comments powered by Disqus