
- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 09-10-2020 08:09 AM
We found that ServiceNow's scheduled exports are great for table data, but the very first NOTE for export sets- "Export sets do not export attachments to records. To download an attachment, either use the REST Attachment API (HTTP request originates from a third-party HTTP client), or use the outbound REST Message module to send the attachment from the instance (HTTP request originates from the instance)." In many cases a simple REST call would be used but for our use-case we found that our internal systems and schedulers were a bit more locked down and using REST really wasn't an option. They could, however access internal servers - such as a MID server.
We then examined the scheduled export process and found it could actually be used to export attachments. We just couldn't use the OOB process, so instead we created a simple function. It uses all the same core components and methods that scheduled exports uses, but works on demand and exclusively with attachments.
EDIT: This also works for dropping the file(s) into a specific folder path within the mid servers export folder. You can add a new function variable such as export_folder and then modify xmlString variable (ie: '<stream_relay_sink path="\/' + export_folder + '\/' + new_attachment_name + '" type=\"FileSink\"/>' ).
/* exportToMid - Function to export a *specific* attachment to a mid servers
* export folder.
*
* Usage: exportToMid("my_file_to_export.pdf", "incident", "12345678910111213", "MIDSERVER001")
*
* @param attachment_name {string} - Specific attachment file name
* @param attached_table {string} - Table the file is attached
* @param attached_record {sys_id} - SYS_ID of the record the file is attached
* @param mid_name {string} - MID Server name
* @return {null}
*/
function exportToMid(attachment_name, attached_table, attached_record, mid_name) {
/** TODO: Add Error Control and validation **/
// Create ECC attachment record used to send the file to the mid server
var ecc_att = new GlideRecord('ecc_agent_attachment');
ecc_att.initialize();
ecc_att.name = 'Export Set Attachment';
ecc_att.short_description = 'exportToMid: ' + attachment_name;
ecc_att.insert();
// Copy attachments (OOB Function copies all attachments)
GlideSysAttachment.copy(attached_table,attached_record,'ecc_agent_attachment',ecc_att.sys_id);
// Get the SYS_ID of the exact attachment file to be exported and used in ECC Payload
var at = new GlideRecord('sys_attachment');
at.addQuery('table_name', 'ecc_agent_attachment');
at.addQuery('table_sys_id', ecc_att.sys_id);
at.addQuery('file_name', attachment_name);
at.query();
at.next();
// Create XML for ECC Payload
var xmlString = '<?xml version="1.0" encoding="UTF-8"?>' +
'<parameters>' +
'<parameter name=\"stream_relay_response_topic\" value=\"ExportSetResult\"/>' +
'<stream_relay_source attachment_sys_id=\"' + at.sys_id + '\" type=\"AttachmentSource\"/>' +
'<stream_relay_transform attachment.table_sys_id=\"' + ecc_att.sys_id + '\" order=\"0\" stream_relay_transfer_progress_interval=\"150\" type=\"AttachmentProgressTransformer\"/>' +
'<stream_relay_sink path="\/' + attachment_name + '\" type=\"FileSink\"/>' +
'</parameters>';
// Create ECC Record
var eccQueue = new GlideRecord('ecc_queue');
eccQueue.initialize();
eccQueue.agent = 'mid.server.' + mid_name;
eccQueue.topic = 'StreamPipeline';
eccQueue.queue = 'output';
eccQueue.state = 'ready';
eccQueue.payload = xmlString;
eccQueue.insert();
}
- 11,477 Views
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Awesome!! that was really helpful for me!
I used it as a base to adapt it to my requirement
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks for this code. I have a requirement where we have to create a CSV file and attach it with a change record. We need to export this file to MID server. Can you tell me how to achieve this one utilising the above script?

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I would have to know more about your requirement. However if I am understanding, you could write a business rule based on the change being approved or in some state, checking for attachments to the change and then executing the above function to initiate the file transfer to a mid server.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks.
Can we define a specific folder path that is present in MID server in the payload or the ecc_queue record?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi
This is a bit new to me, I think I'm completely overlooking where I need to specify my attachment name, table, sys ID and MID...
Could you kindly give me a kick in the right direction please?
Cheers
Taylor

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi TJ,
To answer your question I would need to know more about how you are trying to use it. Normally the code would be put in a script include or directly into from a script block. In the latter; you can paste the function into your script block (Server Side), and utilize the "usage" example above for the format (substituting your instance values for those in the example above).
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi
What is the default Midserver path that the file will be written to ?
I have given a specific export path but I still do not see any file written to the midserver.
I see an entry in ECC Queue, but the file is not being written into the Midserver.
Thank You.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi, I just set this up and it works.
To answer your query, I had to create an 'export' folder within the 'agent' folder. Once I did this the file was written to the 'export' folder as expected.
Geoff
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
This article works like a charm .
One struggle we had is to check in MID Server where the file is located.
The way to validate the successful File Transfer
>> Go to Export >> folder which you have specified while transferring the file in script.
Note: - We were able to transfer both .pdf and .txt file type
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Create ECC attachment record used to send the file to the mid server
var attachment_name = "Complete.txt"; <replace with your file name>
var mid_name = "MID_Server_SCG_BIC_DEV"; < replace with your MID server name>
//var ecc_att = new GlideRecord('ecc_agent_attachment');
//ecc_att.initialize();
//ecc_att.name = 'Export Set Attachment';
//ecc_att.short_description = 'exportToMid: ' + attachment_name;
//ecc_att.insert();
// Copy attachments (OOB Function copies all attachments)
//GlideSysAttachment.copy(attached_table,attached_record,'ecc_agent_attachment',ecc_att.sys_id);
// Get the SYS_ID of the exact attachment file to be exported and used in ECC Payload
var at = new GlideRecord('sys_attachment');
at.addQuery('table_name', 'ecc_agent_attachment');
at.addQuery('table_sys_id', <sys_id_of_ecc_agent_attachment_record>);
//at.addQuery('file_name', attachment_name);
at.query();
at.next();
//gs.info('>>>> PRINT SYS ID>>'+at.getUniqueValue());
var export_folder = 'vim/ivbarcode'; < replace with the file path that you wish to create>
// Create XML for ECC Payload
var xmlString = '<?xml version="1.0" encoding="UTF-8"?>' +
'<parameters>' +
'<parameter name=\"stream_relay_response_topic\" value=\"ExportSetResult\"/>' +
'<stream_relay_source attachment_sys_id=\"' + at.sys_id + '\" type=\"AttachmentSource\"/>' +
'<stream_relay_transform attachment.table_sys_id=\"' + "48279b7adb01a11050bea0bdd39619c3" + '\" order=\"0\" stream_relay_transfer_progress_interval=\"150\" type=\"AttachmentProgressTransformer\"/>' +
'<stream_relay_sink path="\/' + export_folder + '\/' + attachment_name + '" type=\"FileSink\"/>' +
'</parameters>';
// Create ECC Record
var eccQueue = new GlideRecord('ecc_queue');
eccQueue.initialize();
eccQueue.agent = 'mid.server.' + mid_name;
eccQueue.topic = 'StreamPipeline';
eccQueue.queue = 'output';
eccQueue.state = 'ready';
eccQueue.payload = xmlString;
eccQueue.insert();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi @johnstettin ,
Thank you for the great article, but could you tell me where to write this script?
I checked the scheduled data export table, but did not understand where to define the script.
Best Regards,
Aki
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
@Aki18 depends on the use case. For example I added the script to a flow designer action script step; since my use case was to transfer an attachment as part of a flow. What is your use case?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
@Geoff_T ,
Thank you for your reply. My use case is like export record attachments to MID server on a daily basis and also on-demand.
One of my idea is to use Background script, but do you have any other recommendations?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
@Aki18 you could use flow designer that could be set up to execute on schedule or on demand. Create a custom action with a script step to host the sample script from this article. That would be a good approach. Give it a shot and if you are having real difficulties post a new question on the forum and I can help.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I am getting "Not in GZIP format" error in input ecc queue. Any suggestions?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I've managed to get this working using the following solution in Flow Designer
Build the attachment in an action
Inputs and map those into the same inputs on the script step
(function execute(inputs, outputs) {
var attach = new GlideSysAttachment();
//set up inputs
var rec = new GlideRecord(inputs.tableName);
rec.get(inputs.recordSysID);
var fileName = inputs.fileName;
var contentType = inputs.contentType;
var content = inputs.content;
var agr = attach.write(rec, fileName, contentType, content);
outputs.attachment = agr;
})(inputs, outputs);
Outputs > again map that from script step
Send CSV to MID
Subflow that takes the file name from the above as an input. Look up an attachment record that matches the attachment created.
Script step to send CSV to MID server
(function execute(inputs, outputs) {
// ... code ...
var gr = GlideRecord('sys_attachment');
gr.addQuery('sys_id', inputs.csv); //sysid of attachment
gr.query();
if (gr.next())
{
var sa = new GlideSysAttachment();
var binData = sa.getBytes(gr);
var encData =GlideStringUtil.base64Encode(binData);
var jspr = new JavascriptProbe('MIDSERVERNAME');
jspr.setName('ADGroupRequest'); // This can be any name
jspr.setJavascript("var ddr = new ADAttachment(); res= ddr.execute();");
jspr.addParameter("verbose","true");
jspr.addParameter("filepath", 'C://ServiceNow//MID Server DEV//agent//csvs');
jspr.addParameter("filename",gr.file_name);
jspr.addParameter("encodedData",encData);
jspr.create();
}
})(inputs, outputs);
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hello @johnstettin
Your script looks great to me. I am trying to see if I can implement your code for my business requirements. I try to script export the records with an attachment to xml. I'm thinking to myself how to extract the attachment out of xml? Also, the business wants to put those files into a network-shared folder. I like your idea to put those files on mid-server first. I would love to have your input on this or anyone else who commented below. Thanks
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hello @johnstettin
My csv file is not transfered to the mid server and the topic ExportSetResult stays in ready state and never change, can you or anyone help me know how to manage this pleaase ? (i used the exacte script in a scheduled job script and un click execute now to test immediatly)
thank you in advance !

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
@SnowDevOps
The attachments should be Base64 encoded and could be parsed and re-assembled. You should be able to extract the attachment from the xml and then send it to a network share via something like powershell. Or it might be even easier to have a flow execute on the mid server that could accomplish the same thing (depending on your SN FD licensing).
@zineberrada
Its a bit difficult to debug without knowing more but, it sounds like the mid server isn't picking up the ECC record. Double check that your specifying a validated and correct mid server.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hello @johnstettin,
Thank you so much for your reply, i really appreciate it, actually i wasn't checking the correct path because initialy i was defining a custom path here :
xml += '<stream_relay_sink path="/FTP/BSS/' + filename + '" type="FileSink"/>';
However, I found that the default path is actually /agent/export. I discovered this by running the following Linux command :
find / -name *Extracted*
Additionally, the ExportSetResult topic always stays in the "ready" state, due to the following parameter:
xml += '<parameter name="skip_sensor" value="true"/>';