Some PDIs are currently unavailable, and PDI actions are paused. View the latest updates here. Read More

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