There have been a lot of questions on the Service-Now.com community forums lately about getting image fields populated in ServiceNow through an integration.

I did some research and found that with a bit of a modification on the SoapAttachments Script Include, you can quickly populate your image fields with photos using SOAP Web Services, just as you would any attachment through SOAP.

First of all, if you need a primer on sending attachments to Service-now.com via SOAP, you will want to check out the AttachmentCreator documentation page.

In order to embed images in image fields of a table, such as the sys_user table, you simply make the attachment’s filename the same name as the field on that table. For example, on the sys_user table, there is a “photo” field. When uploading an attachment in service-now, you will want the filename to be “photo” (no extension) also.

By doing this you are telling your form to display the contents of the first attachment with the name of “photo” on that record.

That solves the issue of the photo displaying automatically in the form. However, you are still going to see that a file is attached to the record. (see the screen shot below):

There is a way that ServiceNow automatically hides that attachment so that it only displays the contents in the form and doesn’t look like an image attached to the record. To do this, you have to go to the “Sys_Attachment” table and rename the “Table Name”, prepending the string “ZZ_YY” to the table name. This is a convention that service-now uses to hide the attachment icon from the record for that image. (see the screen shot below):

Now, I am going to show you how to enhance the SOAP Attachment libraries to do the following:

  1. Post your image via SOAP so that the contents show up in the form
  2. Hide the Attachment Icon for that image

Really, the only modification that we need to do is to change one method to the SoapAttachments library and then add a few more functions to that library.

Open the “SoapAttachments” script include file in your instance.

At the very bottom of the script, you will find the method, “createAttachmentFromEccQueue”. Replace that method with the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
createAttachmentFromEccQueue : function(){
      var StringUtil = Packages.com.glide.util.StringUtil;
     
      //var normalized = this.eccQueueRecord.payload.replaceAll('\n',"");
      //gs.log("received payload: " + normalized);
      var value = StringUtil.base64DecodeAsBytes(this.eccQueueRecord.payload);
     
      var tableName = this.getTableName();
      var sys_id = this.getTableRecordSysId();
     
      var filename = this.getFileName();
      var content_type = this.getContentType();
      var attachment = new Attachment();
      this.eccQueueRecord.payload = attachment.write(this.getEmbeddedTableName(tableName), sys_id, filename, content_type, value);
      if( this.isEmbeddedTable(tableName) ){
        this.setEmbeddedTableName(this.getEmbeddedTableName(tableName), sys_id, filename);
      }
   },

   /*
    * If a table sent to the script begins with ZZ_YY then it
    * is an embedded table name.  We will strip it off and return
    * the real table name.  If it is not an embedded table name
    * then we just return the original string.
    * */

   getEmbeddedTableName : function( reportedTableName ){
      var tokens = /^ZZ_YY(.*)$/(reportedTableName);
      if(tokens && tokens.length>1){
        return tokens[1];
      }
      return reportedTableName;
   },
   
   /*
    * If the table sent to the script begins with ZZ_YY then it
    * is an embedded table name.  Return true if embedded table
    * or false otherwise
    */

   isEmbeddedTable : function ( reportedTableName ){
      if( reportedTableName != this.getEmbeddedTableName(reportedTableName)){
        return true;
      }
      return false;
   },
   
   /*
    * Prepends ZZ_YY to an attachment's table name
    * if it is not already prepended.
    */

   setEmbeddedTableName : function( tableName, recordId, filename ){
       var att = new GlideRecord("sys_attachment");    
       att.addQuery("table_name", tableName);
       att.addQuery("table_sys_id", recordId);
       att.addQuery("file_name", filename);
       att.orderByDesc("sys_created_on");
       att.query();
       
       if(att.next()){
           if(!this.isEmbeddedTable(att.table_name)){
              att.table_name = "ZZ_YY"+att.table_name;
              att.update();
           }
       }
   }

Save your script include and that should be the only modification you have to make to the script. What you did was modify the “createAttachmentFromEccQueue” method to check to see if the SOAP attachment is using a ZZ_YY prefix on the table name. If it is, it strips that in order to create the attachment, and then it prepends it back again.

Now, in order to send the attachment via SOAP, you simply follow the instructions from the AttachmentCreator documenation, but instead:

  1. Make the <name> tag contain the field name for the form (in sys_user’s case, it is “photo”)
  2. Make the <source> tag prepend “ZZ_YY” to the table name.

So, if we use the Example SOAP Message in the Wiki example, and we do a photo for the sys_user table, we would make the following changes:

1
<name>john1.txt:text/plain</name>

becomes:

1
<name>photo:image/jpeg</name>

And then

1
<source>incident:e6eed6950a0a3c59006f32c8e3ff3cf9</source>

becomes:

1
<source>ZZ_YYsys_user:RECORD_SYS_ID_GOES_HERE</source>

where you replace “RECORD_SYS_ID_GOES_HERE” with the sys_id of the user that is getting this photo.

That should do it. You can now send photos via SOAP and have them appear in embedded form fields.