Unzip a file using script
In one of the integration, the zip file was sent as a response. Due to the complexity of data I had to parse it manually and cannot use Data source. When I searched around, cannot find any solution. So I build the below logic to unzip the file using the mid server. Initially, I thought of sending the file to Lambda and unzipping. If I have to connect, I have to use the mid server. So I did the unzipping in the mid server and sending it back. There may be lot of other way to do this, please let me know in case of any better solution.
Implementation details
Please note, the whole process is done asynchronously. I break down into 2 step process because of the size of the data. You can change this to 1 step process and you can modify the code to get the file contents back instead of file names.
Round 1
- Once zip file is received, it is attached to a record in table_x(here u_bd_transaction)
- Script action will trigger Javascript probe to process the zip file. Attachment data sent as base64 encoded data.
- Midserver script include(java based) will get the write the file to file system, unizp and write the content in file system. Javascript probe will return the list of file names and its path.
Round 2
- Once the response from the midserver is received, business rule in the ECC queue to trigger separate calls to get the file contents.
- Once file content is received, it can be attached to the same record in table_x.
//script action. Event name: attachment.uploaded, condition: event.parm1 == 'u_bd_transaction'
var lib = new CMDBDiscoveryHelper();
lib.handleAttachmentsOnBDTransaction(event.parm2, event.instance);
Script include:
var CMDBDiscoveryHelper = Class.create();
CMDBDiscoveryHelper.prototype = Object.extendsObject(AbstractAjaxProcessor, {
handleAttachmentsOnBDTransaction: function(table_sys_id, attachment_sys_id) {
var gr = new GlideRecord('sys_attachment');
if (gr.get(attachment_sys_id)) {
if (gr.file_name.indexOf(".zip") > -1) {
var stringUtil = new GlideStringUtil();
var sa = new GlideSysAttachment();
var data = stringUtil.base64Encode(sa.getBytes(gr));
var jspr = new JavascriptProbe(this.getMidServer());
jspr.setName('FileZipUtil'); //Any descriptive name will do
jspr.addParameter("verbose", "true");
jspr.addParameter("encoded_data", data);
jspr.addParameter("file_name", gr.file_name);
jspr.addParameter("request_type", "initiate_file_transfer");
jspr.addParameter("bd_transaction_sys_id", table_sys_id);
jspr.setJavascript('var connector = new FileZipUtil(); res = connector.execute();');
jspr.addParameter("skip_sensor", true);
jspr.create();
var u_bd_transaction = this.getRecordForInsertorUpdate('u_bd_transaction', "sys_id=" + table_sys_id);
u_bd_transaction.u_status = 'Unzip request submitted';
u_bd_transaction.u_work_notes = "Unzip request submitted";
this.handleInsertOrUpdate(u_bd_transaction);
} else {
gs.log('Triggering handleBDIntegration ' + attachment_sys_id, 'CMDBDiscoveryHelper');
this.handleBDIntegration(attachment_sys_id, table_sys_id);
var u_bd_transaction = this.getRecordForInsertorUpdate('u_bd_transaction', "sys_id=" + table_sys_id);
u_bd_transaction.u_status = 'XML Processing Started';
u_bd_transaction.u_work_notes = "Processing XML: " + gr.file_name;
this.handleInsertOrUpdate(u_bd_transaction);
}
}
},
handleInboundXMLFile: function() {
try {
var xmlObj = this.getPayload(current.sys_id);
var json_result = JSON.parse(xmlObj.results.result.output);
//gs.log(json_result, "CMDBDiscoveryHelper");
var u_bd_transaction = this.getRecordForInsertorUpdate('u_bd_transaction', "sys_id=" + json_result.bd_transaction_sys_id);
for (var key in json_result.files) {
var file_obj = json_result.files[key];
gs.log(file_obj.file_name, "CMDBDiscoveryHelper");
if (json_result.request_type == "initiate_file_transfer") {
var jspr = new JavascriptProbe(this.getMidServer());
jspr.setName('FileZipUtil'); //Any descriptive name will do
jspr.addParameter("verbose", "true");
jspr.addParameter("file_name", file_obj.file_name);
jspr.addParameter("requested_file_path", file_obj.file_path);
jspr.addParameter("request_type", "get_file_content");
jspr.addParameter("bd_transaction_sys_id", json_result.bd_transaction_sys_id);
jspr.setJavascript('var connector = new FileZipUtil(); res = connector.execute();');
jspr.addParameter("skip_sensor", true);
jspr.create();
u_bd_transaction.u_work_notes = "XML File: " + file_obj.file_name;
this.handleInsertOrUpdate(u_bd_transaction);
} else if (json_result.request_type == "get_file_content") {
u_bd_transaction.u_work_notes = "Saving XML File: " + file_obj.file_name;
this.handleInsertOrUpdate(u_bd_transaction);
var sa = new GlideSysAttachment();
sa.write(u_bd_transaction, file_obj.file_name, 'text/xml', GlideStringUtil.base64DecodeAsBytes(file_obj.file_content));
}
}
this.handleInsertOrUpdate(u_bd_transaction);
} catch (ex) {
this.handleExceptionMessage('Error occured', ex);
//this.createOrUpdateIncidentRecord("Error in processing ZIP File", "Error in processing ZIP File", "CMDBDiscoveryHelper");
}
},
getPayload: function(ecc_sys_id) {
var xmlObj = {};
var gr = new GlideRecord('ecc_queue');
if (gr.get(ecc_sys_id)) {
var payload = gr.payload + '';
if (payload == "<see_attachment/>") {
var sa = new GlideSysAttachment();
payload = sa.get(gr, 'payload');
}
}
return gs.xmlToJSON(payload);
},
getMidServer: function() {
var gr = new GlideRecord('ecc_agent');
if (gs.getProperty('instance_name') == "mycompanydev" || gs.getProperty('instance_name') == "mycompanyqa")
gr.addEncodedQuery('host_name=hostname.compamyname.com');
else
gr.addEncodedQuery("u_functions=WINAD");
gr.orderByDesc('status');
gr.orderByDesc('stopped');
gr.query();
if (gr.next()) {
return gr.name;
}
return '';
},
getRowCount: function(table_name, encoded_query) {
var count = new GlideAggregate(table_name);
count.addEncodedQuery(encoded_query);
count.addAggregate('COUNT');
count.query();
var result = 0;
if (count.next())
result = count.getAggregate('COUNT');
return result;
},
getRecordForInsertorUpdate: function(table_name, encoded_query) {
var gr = new GlideRecord(table_name);
gr.addEncodedQuery(encoded_query);
gr.setLimit(1);
gr.query();
if (gr.next()) {
return gr;
} else {
gr.newRecord(); // create a new record and populate it with default values
return gr;
}
},
handleInsertOrUpdate: function(gr) {
if (gr.isNewRecord()) {
gr.insert();
} else {
gr.update();
}
},
handleExceptionMessage: function(textMessage, exception) {
gs.addInfoMessage(textMessage + exception);
gs.error(textMessage + exception.stack, 'CMDBDiscoveryHelper');
},
type: 'CMDBDiscoveryHelper'
});
Midserver script include:
var FileZipUtil = Class.create();
FileZipUtil.prototype = {
File: Packages.java.io.File,
FileInputStream: Packages.java.io.FileInputStream,
FileOutputStream: Packages.java.io.FileOutputStream,
ZipEntry: Packages.java.util.zip.ZipEntry,
ZipInputStream: Packages.java.util.zip.ZipInputStream,
JavaString: Packages.java.lang.String,
Base64: Packages.org.apache.commons.codec.binary.Base64,
FileUtils: Packages.org.apache.commons.io.FileUtils,
initialize: function() {
this.verbose = probe.getParameter("verbose");
this.file_name = probe.getParameter("file_name");
this.encoded_data = probe.getParameter("encoded_data");
this.request_type = probe.getParameter("request_type");
this.requested_file_path = probe.getParameter("requested_file_path");
this.result = {
messages: [],
files: [],
bd_transaction_sys_id: probe.getParameter("bd_transaction_sys_id"),
request_type: this.request_type
};
},
execute: function() {
try {
this.debug("here is the debug message " + this.request_type);
if (this.request_type == "initiate_file_transfer") {
var destDir = new this.File("." + this.File.separator + "BD_processor");
if (!destDir.exists())
destDir.mkdir();
var data = this.Base64.decodeBase64(this.encoded_data);
var stream = new this.FileOutputStream(destDir.getCanonicalPath() + this.File.separator + this.file_name);
stream.write(data);
stream.close();
var fileZip = destDir.getCanonicalPath() + this.File.separator + this.file_name;
var empty_str = new Packages.java.lang.String("test");
var buffer = empty_str.getBytes();
var zis = new this.ZipInputStream(new this.FileInputStream(fileZip));
var zipEntry = zis.getNextEntry();
while (zipEntry != null) {
if (zipEntry.getName().indexOf(".xml") > -1) {
var newFile = this.newFile(destDir, zipEntry);
var fos = new this.FileOutputStream(newFile);
var len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
var zip_file = new this.File(destDir, zipEntry.getName());
//var fileContent = this.FileUtils.readFileToByteArray(zip_file);
//var encodedString = this.Base64.encodeBase64String(fileContent);
this.result.files.push({
file_name: zipEntry.getName(),
file_path: zip_file.getCanonicalPath()
});
}
zipEntry = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
//var downloaded_zip = new this.File(destDir.getCanonicalPath() + this.File.separator + this.file_name);
//downloaded_zip.delete();
} else if (this.request_type == "get_file_content") {
var zip_file = new this.File(this.requested_file_path);
var fileContent = this.FileUtils.readFileToByteArray(zip_file);
var encodedString = this.Base64.encodeBase64String(fileContent);
this.result.files.push({
file_name: this.file_name,
file_content: encodedString
});
//zip_file.delete();
}
} catch (e) {
this.debug(e.toString());
}
return JSON.stringify(this.result);
},
newFile: function(destinationDir, zipEntry) {
var destFile = new this.File(destinationDir, zipEntry.getName());
return destFile;
},
debug: function(m) {
if (this.verbose == "true") {
ms.log(m);
this.result.messages.push(m);
}
},
type: 'FileZipUtil'
};
Business rule:
//business rule: table: ecc_queue, When: asynch, condition: topic=JavascriptProbe^queue=input^name=FileZipUtil
var library = new CMDBDiscoveryHelper();
library.handleInboundXMLFile();
https://www.servicenow.com/community/now-platform-articles/unzip-a-file-using-script/ta-p/2296277