I
am really enjoying being here at Knowledge 10 and meeting so many of you who read our posts. I have been busy in one-on-one sessions hearing requests and helping come up with answers. One of our readers wanted to know how they would go about downloading all of the attachments on a record as a zip file. Another reader wanted to know how to send attachments as a zip file via a web service. I believe this post should help solve both questions.
The challenge we will solve in this post is this: if a record has any attachments, we will add a button to the form that allows you to download all of the attachments as a single ZIP file.
Name:Save Attachments as ZIP
Condition:
Script:
action.setRedirectURL('exportAttachmentsToZip.do?sysparm_sys_id=' + current.sys_id + '&sysparm_table=' + current.getTableName());
The only real secret to the above code is the setRedirectURL. This allows us to call a processor in our system that will popup a download dialog to download the zip file. The exportAttachmentsToZip processor does not yet exist in the system and will need to be created. Processors are found under System Definition->Processors.
Create a new processor. Processors are found under System Definition->Processors.
Name: exportAttachmentsToZip
Type: script
Path: exportAttachmentsToZip
Script:
var table = g_request.getParameter('sysparm_table');
var theRecord = new GlideRecord(table);
theRecord.addQuery('sys_id', sysid);
theRecord.query();
theRecord.next();
var zipName = 'attachments.zip';
var StringUtil = Packages.com.glide.util.StringUtil;
var gr = new GlideRecord('sys_attachment');
gr.addQuery('table_sys_id', theRecord.sys_id);
gr.addQuery('table_name', theRecord.getTableName());
gr.query();
gs.log('sys_id: ' + theRecord.sys_id);
gs.log('table: ' + theRecord.getTableName());
if (gr.hasNext()){
g_response.setHeader('Pragma', 'public');
g_response.addHeader('Cache-Control', 'max-age=0');
g_response.setContentType('application/octet-stream');
g_response.addHeader('Content-Disposition', 'attachment;filename=' + zipName);
var out = new Packages.java.util.zip.ZipOutputStream(g_response.getOutputStream());
var count=0;
while (gr.next()){
var sa = new Packages.com.glide.ui.SysAttachment();
var binData = sa.getBytes(gr);
var file = gr.file_name;
this.addBytesToZip(out, zipName, file, binData);
gs.log('Adding ' + file + ' to ' + zipName);
count ++;
}
gs.log('Added ' + count + ' files');
// Complete the ZIP file
out.close();
}
function addBytesToZip (out, dir, file, stream){
// Add ZIP entry to output stream.
out.putNextEntry(new Packages.java.util.zip.ZipEntry(file));
out.write(stream, 0, stream.length);
out.closeEntry();
}
That’s all there is to it. The result will appear like the following screen shot.

Comments
Posted On
Apr 24, 2010Posted By
ElPuntoJacob, thanks for the article.
I tried the code but there seems to be aproblem with the zip format. It’s not recognized by pkzip and other zip tools. One of the differences is that it has set the general purpose bit 3 (0×0008)(crc,compressed/uncompressed zero in header) and pkzip uses bit 1 (0×0002). Compression method is both 8 (0×0008) but that should not be a problem.
Posted On
Apr 25, 2010Posted By
ElPuntoForget the previous remark,
It works OK. Because I used the Java Script Editor plugin it messed up the layout.
The final close was missing and that caused an incomplete dictionary entry. I will now try and integrate it in my Webservice.
Posted On
May 26, 2010Posted By
ElPuntoJacob,
Currently I use a Business Rule to create the SOAP request. Is it possible to call the processor to retrieve the base64encoded ZIp information and add it to the body ?.
My BR code looks like this:
env = new SOAPEnvelope();
env.createNameSpace(“xmlns:ns1″, gns);
var hdr = env.createHeaderElement(‘ns1:AuthenticationInfo’, null, ‘mustUnderstand’, ’0′);
hdr.setAttribute(‘actor’, ‘http://www.w3.org/2001/XMLSchema-instance‘);
hdr.createElement(env, ‘ns1:userName’, gs.getProperty(‘com.snc.interface.tibco.user_name’));
hdr.createElement(env, ‘ns1:password’, gs.getProperty(‘com.snc.interface.tibco.user_password’));
gs.log( ‘Created Header’ );
// Fill static Tibco fields
var bdy = env.createBodyElement(‘ns1:’+ gs.getProperty(‘com.snc.interface.tibco.soap_operation’));
gs.log( ‘Soap Operation: ‘ + gs.getProperty(‘com.snc.interface.tibco.soap_operation’));
env.createElement(bdy, ‘ns1:messagetype’ , gaction);
env.createElement(bdy, ‘ns1:messagecreated’ , cvtDateTime(gs.daysAgo(0)));
env.createElement(bdy, ‘ns1:application’ , gmessagetype);
env.createElement(bdy, ‘ns1:supplier’ , gsupplier);
env.createElement(bdy, ‘ns1:supplier_id’ , gsupplierid);
env.createElement(bdy, ‘ns1:attachment_filename_1′, ‘attachment.zip’);
env.createElement(bdy, ‘ns1:attachment_content_1′ , gattachcontent);
..etc
Can I use the Processor to fill the variable gattachcontent with the base64encoded query ?
What’s the most simple way to base64encode the produced Zip file ?
Best regards
Posted On
May 27, 2010Posted By
Jacob AndersenYou’ll want to look at this post:
http://www.servicenowguru.com/integration/sending…
Good luck!