How to export excel file from ‘sys_attachent’ table to midserver

satyakumars
Tera Contributor

Hi everyone

I have requirement to export excel file from ‘sys_attachment’ table from servicenow to midserver file path location. I need variable information also so ‘export sets’ feature won’t help me in this case.

so something like flow designer with custom script am looking for. Can anyone please how to achieve this ?

 

2 REPLIES 2

Matthew_13
Mega Sage

Hi Buddy,

At a high level, the reason this feels hard is because ServiceNow cannot directly write files to a MID Server’s filesystem. Anything that ends up on the MID has to be executed by the MID itself not by the instance.

So the pattern is:

Flow runs on the instance → instance sends the file to the MID → MID writes it locally

Since Export Sets won’t work for you (because you need variables), the clean approach is a Flow + custom server-side script + MID execution.

In simple terms:

  1. Flow triggers (manual, scheduled, or record-based).

  2. A Script step in Flow:

    • Reads the Excel attachment from sys_attachment

    • Encodes it (base64)

    • Sends it to the MID using the ECC queue

  3. The MID Server receives the payload and:

    • Decodes the file

    • Writes it to the specified directory on disk

That’s it conceptually.

Key points to keep in mind:

  • You cannot write directly to D:\ or /opt/… from a Glide script.

  • The MID must be explicitly told to do the write.

  • The MID service account must have OS-level write permissions to the folder.

Why Flow Designer works here:

  • Flow handles the “when” and “which attachment”

  • The custom script handles “read attachment + send to MID”

  • The MID script handles “write file locally”

Where your variable data fits:

  • Include variables in the payload you send to the MID

  • Either:

    • add them to the filename, or

    • write a companion .json file next to the Excel file

If you want this to be simpler and you have IntegrationHub / Orchestration, there may already be a MID-capable “write file” action you can reuse. Without it, the ECC + MID script pattern above is the standard and supported way to do this. I hope this helps 🙂

 

@satyakumars - Please mark Accepted Solution and Thumbs Up if you found Helpful!

MJG

satyakumars
Tera Contributor

@Matthew_13  - I appreciate your time. I tried using javascriptprobe and its not supporting. Then tried with below script, flow was successful but ecc queue record shows error as "

Could not download file because: Given table does not match attachment table:ecc_agent_attachment vs. sys_email".  Any idea ?

(function execute(inputs, outputs) {

    // 1. Get attachment record
    var attGR = new GlideRecord('sys_attachment');
    if (!attGR.get(inputs.attachment_sys_id)) {
        throw 'Attachment not found: ' + inputs.attachment_sys_id;
    }

    var attachmentSysId = attGR.getUniqueValue();
    var tableName = attGR.getValue('table_name');
    var tableSysId = attGR.getValue('table_sys_id');
    var fileName = attGR.getValue('file_name');

    // 2. Target directory
    var targetDir = inputs.target_directory || 'C:\\temp\\servicenow\\';
    var fullPath = targetDir + fileName;

    // 3. Build StreamPipeline XML
    var payload =
        '<parameters>' +
        '<stream_relay_source ' +
            'type="AttachmentSource" ' +
            'attachment_sys_id="' + attachmentSysId + '" ' +
            'attachment_table_name="' + tableName + '" ' +
            'attachment_table_sys_id="' + tableSysId + '"/>' +

        '<stream_relay_transform ' +
            'type="AttachmentProgressTransformer" ' +
            'order="0"/>' +

        '<stream_relay_sink ' +
            'type="FileSink" ' +
            'path="' + fullPath + '"/>' +
        '</parameters>';

    // 4. Insert ECC Queue output record
    var eccGR = new GlideRecord('ecc_queue');
    eccGR.initialize();
    eccGR.queue = 'output';
    eccGR.agent = inputs.mid_server_1;
    eccGR.topic = 'StreamPipeline';
    eccGR.name = 'ExportAttachmentToMID';
    eccGR.payload = payload;
    eccGR.state = 'ready';
    eccGR.insert();

})(inputs, outputs);