Moving Attachments to a different ServiceNow instance
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-20-2024 08:08 AM
I had a case were I needed to move Case back to OOB. I exported all of the case records, made my changes and imported the case records into their respective case type table. So now I need re-attach the attachments. As part of the import, I moved the old case number into the correlation id field on the imported case record.
In our test instance (a clone of PRD prior to moving case to OOB), I created a field on the sys_attachment table called u_correlation_id and ran a script that would do a lookup against the case table and record (based on the table_name and table_sys_id) and move the case number into the u_correlation_id field. I then wrote a script that, using REST post call, would copy over the attachments to other instance. The problem I am seeing is that, while the attachment is getting created on the other instance, it is not bringing over the value in the u_correlation_id field.
function sendAttachment (sourceTable, targetInstanceURL){
var answer = [0,0];
var attachRec = new GlideRecord('sys_attachment');
attachRec.setLimit(10);
attachRec.addQuery('table_name', sourceTable);
attachRec.query();
if(attachRec.hasNext()){
while (attachRec.next()){
var attachMessage = new sn_ws.RESTMessageV2();
attachMessage.setLogLevel('all');
attachMessage.setHttpMethod("post");
attachMessage.setEndpoint(targetInstanceURL+"/api/now/attachment/file");
attachMessage.setQueryParameter("table_name", attachRec.table_name);
attachMessage.setQueryParameter("file_name", attachRec.file_name);
attachMessage.setQueryParameter('table_sys_id', attachRec.table_sys_id);
attachMessage.setQueryParameter('u_correlation_id', attachRec.u_correlation_id);
attachMessage.setRequestHeader("Content-Type", attachRec.content_type);
attachMessage.setRequestHeader("Accept", "application/json");
attachMessage.setRequestBodyFromAttachment(attachRec.sys_id);
var response = attachMessage.execute();
var responseBody = response.getBody();
gs.info('Response Body: ' + responseBody);
var httpStatus = response.getStatusCode();
if (httpStatus.toString() == "201"){
answer[0] += 1;
}else{
answer[1] += 1;
}
}
} else {
answer = "none";
}
gs.info("Number of attachments sent over to target instance: " + answer[0] + " number of attachments not sent over: " + answer[1]);
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-20-2024 08:19 AM
Could you try once by sending the 'u_correlation_id' in attachment metadata instead of query parameter:
function sendAttachment(sourceTable, targetInstanceURL) {
var answer = [0, 0];
var attachRec = new GlideRecord('sys_attachment');
attachRec.setLimit(10); // Remove this or set higher if you need to process more than 10 attachments
attachRec.addQuery('table_name', sourceTable);
attachRec.query();
if (attachRec.hasNext()) {
while (attachRec.next()) {
var attachMessage = new sn_ws.RESTMessageV2();
attachMessage.setLogLevel('all');
attachMessage.setHttpMethod("post");
attachMessage.setEndpoint(targetInstanceURL + "/api/now/attachment/file");
// Set request body to include metadata and attachment
var body = {
table_name: attachRec.table_name.toString(),
file_name: attachRec.file_name.toString(),
table_sys_id: attachRec.table_sys_id.toString(),
u_correlation_id: attachRec.u_correlation_id.toString()
};
// Attach the request body and file as part of the POST request
attachMessage.setRequestHeader("Content-Type", attachRec.content_type);
attachMessage.setRequestHeader("Accept", "application/json");
attachMessage.setRequestBodyFromAttachment(attachRec.sys_id);
// Add the attachment metadata into the body as parameters
attachMessage.setStringParameterNoEscape("table_name", attachRec.table_name.toString());
attachMessage.setStringParameterNoEscape("table_sys_id", attachRec.table_sys_id.toString());
attachMessage.setStringParameterNoEscape("u_correlation_id", attachRec.u_correlation_id.toString());
// Execute the REST message
var response = attachMessage.execute();
var responseBody = response.getBody();
gs.info('Response Body: ' + responseBody);
var httpStatus = response.getStatusCode();
if (httpStatus.toString() == "201") {
answer[0] += 1;
} else {
answer[1] += 1;
}
}
} else {
answer = "none";
}
gs.info("Number of attachments sent to the target instance: " + answer[0] + ", failed attachments: " + answer[1]);
}
i hope my answer helps you to resolve your issue, if yes please mark my answer helpful and correct.
thank you
rajesh
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-20-2024 08:27 AM
Thanks for the reply. I see that you created a body JSON object, but I do not see where you are using it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-20-2024 08:49 AM
Thanks for highlighting, let me fix.
when uploading an attachment via the REST API, you typically need to handle metadata separately because the attachment itself is treated as a file upload. The additional fields you want to populate (like u_correlation_id) should generally be handled in a separate API call after the attachment has been created.
function sendAttachment(sourceTable, targetInstanceURL) {
var answer = [0, 0];
var attachRec = new GlideRecord('sys_attachment');
attachRec.setLimit(10); // Adjust the limit as needed
attachRec.addQuery('table_name', sourceTable);
attachRec.query();
if (attachRec.hasNext()) {
while (attachRec.next()) {
var attachMessage = new sn_ws.RESTMessageV2();
attachMessage.setLogLevel('all');
attachMessage.setHttpMethod("post");
attachMessage.setEndpoint(targetInstanceURL + "/api/now/attachment/file");
// Attach the file using the sys_id of the attachment
attachMessage.setRequestBodyFromAttachment(attachRec.sys_id);
attachMessage.setRequestHeader("Content-Type", attachRec.content_type);
attachMessage.setRequestHeader("Accept", "application/json");
// Execute the REST message to upload the attachment
var response = attachMessage.execute();
var responseBody = response.getBody();
var httpStatus = response.getStatusCode();
gs.info('Response Body: ' + responseBody);
if (httpStatus.toString() == "201") {
answer[0] += 1; // Successful attachment
var responseJSON = JSON.parse(responseBody);
var newAttachmentSysId = responseJSON.result.sys_id; // Capture the new attachment's Sys ID
// Now update the u_correlation_id
var updateMessage = new sn_ws.RESTMessageV2();
updateMessage.setHttpMethod("patch"); // Use PATCH to update the record
updateMessage.setEndpoint(targetInstanceURL + "/api/now/table/sys_attachment/" + newAttachmentSysId);
updateMessage.setRequestHeader("Content-Type", "application/json");
// Construct the body for the update
var updateBody = {
u_correlation_id: attachRec.u_correlation_id ? attachRec.u_correlation_id.toString() : ''
};
updateMessage.setRequestBody(JSON.stringify(updateBody)); // Set the request body
var updateResponse = updateMessage.execute();
var updateResponseBody = updateResponse.getBody();
gs.info('Update Response Body: ' + updateResponseBody);
var updateHttpStatus = updateResponse.getStatusCode();
if (updateHttpStatus.toString() !== "204") {
answer[1] += 1; // Failed to update the correlation ID
}
} else {
answer[1] += 1; // Failed to upload attachment
}
}
} else {
answer = "none";
}
gs.info("Number of attachments sent to the target instance: " + answer[0] + ", failed attachments: " + answer[1]);
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-20-2024 11:11 AM
Got it. Thanks for the help. So it's getting the attachment over and the update to the record is coming back with a http status code of 200, but nothing is set on the record and I'm wondering if it's a timing issue. So I may add a pause in the code and see if that helps.