Jon G Lind
ServiceNow Employee
ServiceNow Employee

Occasionally you may need to preserve the URL of an attachment while also changing its content. For example you have a reference document that needs to be updated from time to time but a user may have already shared or bookmarked the link. 

 

Here I will show you how to accomplish this by taking a new attachment, deleting the old attachment, and cloning the attachment into a new record with the same GUID as before.

 

Steps to Clone

1. Create a new attachment and get its sys id.

2. Query the sys_attachment for the existing record that you wish to replace and grab the table name and table sys id (i.e. the sys id of the record the file is attached to).

3. Delete the old attachment.

4. Update the new attachment and do an insert (i.e. a copy) and use the GlideRecord method setNewGuidValue to specify the old attachment's sys id before calling insert.

5. Copy each record in the sys_attachment_doc (this stores the content of the attachment).

 

NOTE: Inspiration came from a script include that you have on your instance called "AppCreatorCMSCreation".  Check out the _syncPicture method to see something similar being done.

 

Sample Code

// The sys id of the attachment that you wish to preserve
var oldAttachmentSysId = x;

// The sys id of the new attachment to replace the existing
var attachmentToCloneFromSysId = y;

var newAttachmentGr = replaceAttachment(oldAttachmentSysId, attachmentToCloneFromSysId);

function replaceAttachment(oldSysId, newSysId) {
    var attOldGr = new GlideRecord('sys_attachment');
    attOldGr.get(oldSysId);

    var attNewGr = new GlideRecord('sys_attachment');
    attNewGr.get(newSysId);

    attNewGr.setNewGuidValue(oldSysId);
    // If you are cloning from and to the same table
    // (e.g. add new attachment to a record, replace then
    // delete) the following two lines are not needed
    attNewGr.table_sys_id = attOldGr.table_sys_id;
    attNewGr.table_name = attOldGr.table_name;

    // Delete old then immediately replace it with a clone
    attOldGr.deleteMultiple();
    var sysIdAfterInsert = attNewGr.insert();

    // Clone the content from the doc table.
    var attNewDoc = new GlideRecord('sys_attachment_doc');
    attNewDoc.addQuery('sys_attachment', newSysId);

    attNewDoc.query();
    while (attNewDoc.next()) {
        attNewDoc.sys_attachment = oldSysId;
        attNewDoc.insert();
    }

    return attNewGr;
} 
Comments
Jay Uttanoor
Tera Contributor

Thank you for sharing. this worked for a similar issue we had

Version history
Last update:
‎01-05-2023 09:49 AM
Updated by:
Contributors