Using box API [Upload file] from Servicenow
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-15-2024 09:33 PM
Hi Community.
I am trying to connect to box from ServiceNow using background script.
Here is my code.
var table_name = "x_common_center";
var sys_id = "01da168d834d5250e3d896b6feaad333";
var attachment = new GlideSysAttachment();
var agr = attachment.getAttachments(table_name, sys_id); // create attachment GlideRecord
while (agr.next()) {
// for each attachment on the incident record
var file_name = agr.getValue('file_name');
var content_type = agr.getValue('content_type');
gs.info('File Name: ' + file_name);
gs.info('Content Type: ' + content_type);
// Get the content stream (binary data)
var is = attachment.getContentStream(agr.getUniqueValue());
if (!is) {
gs.error('No file content found for attachment: ' + file_name);
continue; // Skip if no file content is found
}
// Define boundary and metadata
var folder_id = "287704293536"; // Replace with actual folder ID in Box
var date = new GlideDateTime();
var formattedDate = date.getValue().replace(" ", "T") + "Z"; // Convert to RFC 3339 format
var boundary = '----WebKitFormBoundary' + date.getNumericValue(); // Define unique boundary
gs.info("Boundary: " + boundary);
var request = new sn_ws.RESTMessageV2('global.Box Test', 'file upload to box');
request.setHttpMethod('POST');
request.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
// Use getStreamWriter() to add boundaries and parameters
var writer = request.getStreamWriter();
// Write attributes part (metadata)
writer.writeString("--" + boundary + "\r\n");
writer.writeString('Content-Disposition: form-data; name="attributes"\r\n\r\n');
writer.writeString('{"name":"' + file_name + '","parent":{"id":"' + folder_id + '"}, "content_created_at": "' + formattedDate + '", "content_modified_at": "' + formattedDate + '"}\r\n');
// Write file part (binary content)
writer.writeString("--" + boundary + "\r\n");
writer.writeString('Content-Disposition: form-data; name="file"; filename="' + file_name + '"\r\n');
writer.writeString('Content-Type: ' + content_type + '\r\n\r\n');
writer.writeStream(is); // Write binary content (file)
writer.writeString("\r\n--" + boundary + "--\r\n");
// Execute the request
var response = request.execute();
var response_body = response.getBody();
var response_code = response.getStatusCode();
// Log the response
gs.info("Response Code: " + response_code);
gs.info("Response Body: " + response_body);
}
According to this source
it should work fine but response always returns: {"message": "API upload did not contain a file part","type":"error"}
Is there any other way to set binary data to reqeuest body?
I would be grateful if anyone has used the Box file upload API before. I have searched every single website I could find, but I still haven't figured out how.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-15-2024 10:05 PM
I have tried a different approach as well.
// Function to fetch the attachment from ServiceNow using GlideRecord
function getAttachmentContent(attachmentSysId) {
var attachmentGR = new GlideRecord('sys_attachment');
if (attachmentGR.get(attachmentSysId)) {
var attachmentContentGR = new GlideRecord('sys_attachment_doc');
attachmentContentGR.addQuery('sys_attachment', attachmentSysId);
attachmentContentGR.query();
var fileContent = '';
while (attachmentContentGR.next()) {
fileContent += attachmentContentGR.getValue('data'); // Attachment data is stored as base64 encoded string
}
var decodedContent = GlideStringUtil.base64Decode(fileContent); // Decode the base64 data
return {
fileName: attachmentGR.getValue('file_name'),
fileData: decodedContent
};
} else {
gs.error("Attachment with sys_id: " + attachmentSysId + " not found.");
return null;
}
}
// Function to construct multipart body content
function createMultipartBody(attributes, fileName, fileData) {
var boundary = "----WebKitFormBoundary" + gs.generateGUID(); // Create a random boundary string
// Build the multipart request body with attributes first and file content second
var body = "";
body += "--" + boundary + "\r\n";
body += 'Content-Disposition: form-data; name="attributes"\r\n\r\n';
body += attributes + "\r\n";
body += "--" + boundary + "\r\n";
body += 'Content-Disposition: form-data; name="file"; filename="' + fileName + '"\r\n';
body += 'Content-Type: application/octet-stream\r\n\r\n';
body += fileData + "\r\n";
body += "--" + boundary + "--\r\n";
return {
body: body,
boundary: boundary
};
}
// Function to upload the file to Box
function uploadFileToBox(fileName, fileData) {
var boxApiUrl = 'https://upload.box.com/api/2.0/files/content';
var accessToken = 'YOUR_BOX_ACCESS_TOKEN';
var parentFolderId = '0'; // Use '0' for root folder or specify a folder ID
var attributes = JSON.stringify({
name: fileName,
parent: {
id: parentFolderId
}
});
var multipart = createMultipartBody(attributes, fileName, fileData);
var request = new sn_ws.RESTMessageV2('global.Box Test', 'file upload to box');
request.setHttpMethod('POST');
request.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + multipart.boundary);
// Set the body of the request
request.setRequestBody(multipart.body);
try {
var response = request.execute();
var responseBody = response.getBody();
var httpStatus = response.getStatusCode();
if (httpStatus === 201) {
gs.info("File uploaded successfully to Box: " + responseBody);
} else {
gs.error("Failed to upload file to Box. Status: " + httpStatus + ", Response: " + responseBody);
}
} catch (ex) {
gs.error("Error uploading file to Box: " + ex.message);
}
}
// Main function to fetch the attachment from ServiceNow and upload it to Box
function uploadAttachmentToBox(attachmentSysId) {
var attachment = getAttachmentContent(attachmentSysId);
if (attachment) {
gs.info("Successfully fetched attachment '" + attachment.fileName + "' from ServiceNow.");
uploadFileToBox(attachment.fileName, attachment.fileData);
}
}
uploadAttachmentToBox('305bd6cd834d5250e3d896b6feaad370');
The upload succeeds, but the file content is corrupted and unreadable.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-15-2024 10:11 PM
Do you get proper logs of the file content or do you get null?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-15-2024 10:42 PM
Thank you for your message. It contains a decoded value, not null at least.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-15-2024 10:53 PM - edited 10-15-2024 10:55 PM
Plus, the thing is box API accepts string (binary) as file, so using [base64Decode] does not make sense.