How to copy attachment to another record

Alon Grod
Tera Expert

Hi,

How can I copy an attachment to specific record with two changes:

No need the ZZ_YY
I want to change the file name on the target record

AlonGrod_0-1785937908345.png

 



1 REPLY 1

Abhishek Pal
Mega Guru

Hi @Alon Grod ,

Do not update sys_attachment.table_name, table_sys_id, or sys_attachment_doc directly.

The ZZ_YY prefix is commonly used for attachment-variable or temporary attachment records. When copying the file, attach it to the actual target GlideRecord using GlideSysAttachment. The new attachment will use the target table name without ZZ_YY.

GlideSysAttachment.copy() is not suitable when you need to rename a specific file because it preserves the original filename and may copy all attachments from the source record.

Use getContentStream() and writeContentStream():

function copyAttachmentWithRename(
sourceAttachmentSysId,
targetTable,
targetRecordSysId,
newFileName
) {
if (!sourceAttachmentSysId || !targetTable ||
!targetRecordSysId || !newFileName) {
throw 'Missing required attachment parameters.';
}

var sourceAttachment = new GlideRecord('sys_attachment');

if (!sourceAttachment.get(sourceAttachmentSysId)) {
throw 'Source attachment was not found: ' +
sourceAttachmentSysId;
}

var targetRecord = new GlideRecord(targetTable);

if (!targetRecord.get(targetRecordSysId)) {
throw 'Target record was not found: ' +
targetTable + ' - ' + targetRecordSysId;
}

// Preserve the original extension when the new name has no extension.
var originalFileName =
sourceAttachment.getValue('file_name') || '';

if (newFileName.indexOf('.') == -1) {
var extensionPosition = originalFileName.lastIndexOf('.');

if (extensionPosition > -1) {
newFileName += originalFileName.substring(
extensionPosition
);
}
}

var attachmentApi = new GlideSysAttachment();
var inputStream = attachmentApi.getContentStream(
sourceAttachmentSysId
);

var newAttachmentSysId =
attachmentApi.writeContentStream(
targetRecord,
newFileName,
sourceAttachment.getValue('content_type'),
inputStream
);

if (!newAttachmentSysId) {
throw 'The attachment could not be copied.';
}

return newAttachmentSysId;
}

Example:

var newAttachmentSysId = copyAttachmentWithRename(
'SOURCE_ATTACHMENT_SYS_ID',
'TARGET_TABLE_NAME',
'TARGET_RECORD_SYS_ID',
'new_file_name.png'
);

gs.info(
'New attachment created: ' + newAttachmentSysId
);

This creates a new attachment with:

- The same file content
- The same content type
- The new filename
- The actual target table and record
- No ZZ_YY prefix on the target attachment

Delete the source attachment only after confirming that the new attachment was created successfully:

new GlideSysAttachment().deleteAttachment(
'SOURCE_ATTACHMENT_SYS_ID'
);

Only perform the deletion when the requirement is to move the attachment rather than copy it.

For a user-triggered implementation, also validate that the user has access to both the source attachment and the target record before executing the copy.

Official reference:

https://www.servicenow.com/docs/r/api-reference/server-api-reference/GlideSysAttachmentGlobalAPI.htm...

Hope this helps!

If this response helped, please mark it as Helpful.
If it resolves your issue, please Accept it as Solution.

Kind Regards,
Abhishek Pal