Download attachments of selected records of a table as a zip with record number appended

Harika Thota
Tera Guru

Hi,

I have a requirement to append file number to the file name in the zip.

below is code.

 

Any leads are appreciated.

UI Action:

function downloadZip() {

    var selectedAttachments = g_list.getChecked(); // If used in list
    if (!selectedAttachments || selectedAttachments.length === 0) {
        alert("No attachments selected.");
        return;
    }
   
    var ga = new GlideAjax('AttachmentZipAjax');
    ga.addParam('sysparm_name', 'getZippedAttachments');
    ga.addParam('sysparm_attachment_ids', selectedAttachments);
    ga.getXMLAnswer(function(response) {
        var base64Zip = response;
        var blob = b64toBlob(base64Zip, 'application/zip');
        var url = URL.createObjectURL(blob);
        var a = document.createElement('a');
        a.href = url;
        a.download = 'attachments.zip';
        a.click();
        URL.revokeObjectURL(url);
    });
}

// Helper to convert Base64 to Blob
function b64toBlob(b64Data, contentType, sliceSize) {
    contentType = contentType || '';
    sliceSize = sliceSize || 512;

    var byteCharacters = atob(b64Data);
    var byteArrays = [];

    for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        var slice = byteCharacters.slice(offset, offset + sliceSize);
        var byteNumbers = new Array(slice.length);

        for (var i = 0; i < slice.length; i++) {
            byteNumbers[i] = slice.charCodeAt(i);
        }

        var byteArray = new Uint8Array(byteNumbers);
        byteArrays.push(byteArray);
    }

    return new Blob(byteArrays, {
        type: contentType
    });
}

Script include:

var AttachmentZipAjax = Class.create();
AttachmentZipAjax.prototype = Object.extendsObject(AbstractAjaxProcessor, {

	getZippedAttachments: function () {
        var ids = this.getParameter('sysparm_attachment_ids');
		//gs.log('Harika AttachmentZipAjax'+ ids);
        if (!ids) return '';
        var zipHelper = new AttachmentZipHelper();
        return zipHelper.zipSelectedAttachments(ids);
    },

    type: 'AttachmentZipAjax'
});

Script include 2:

var AttachmentZipHelper = Class.create();
AttachmentZipHelper.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    zipSelectedAttachments: function(attachmentSysIds) {

        var zip = new Packages.java.util.zip.ZipOutputStream(new Packages.java.io.ByteArrayOutputStream());

        var gr = new GlideRecord('sys_attachment');
        gr.addQuery('table_sys_id', 'IN', attachmentSysIds);
        gr.query();

        var byteStream = new Packages.java.io.ByteArrayOutputStream();
        var zipOut = new Packages.java.util.zip.ZipOutputStream(byteStream);

        while (gr.next()) {
    
                var bin = new GlideSysAttachment().getBytes(gr);
			
                var entry = new Packages.java.util.zip.ZipEntry(gr.getValue('file_name'));
			
                zipOut.putNextEntry(entry);
                zipOut.write(bin, 0, bin.length);
                zipOut.closeEntry();
            }
        zipOut.close();
        return GlideStringUtil.base64Encode(byteStream.toByteArray());
			}
    },
    type: 'AttachmentZipHelper'
});

Thanks,

Harika

 

 

1 ACCEPTED SOLUTION

Harika Thota
Tera Guru

Thanks for the response.

 

I got the solution to append the record number to the file name in zip

 

script include

var AttachmentZipHelper = Class.create();
AttachmentZipHelper.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    zipSelectedAttachments: function(attachmentSysIds) {
        //    gs.log('Harika Helper' + attachmentSysIds);
        var zip = new Packages.java.util.zip.ZipOutputStream(new Packages.java.io.ByteArrayOutputStream());

        var gr = new GlideRecord('sys_attachment');
        gr.addQuery('table_sys_id', 'IN', attachmentSysIds);
        gr.query();

        var byteStream = new Packages.java.io.ByteArrayOutputStream();
        var zipOut = new Packages.java.util.zip.ZipOutputStream(byteStream);

        while (gr.next()) {
            // gs.log('Harika Helper21');
            var gr1 = new GlideRecord('u_wealth_management_task');
             gr1.addQuery('sys_id', gr.table_sys_id);
             gr1.query();
             if (gr1.next()) {
            // Optional: prepend record number
            
                //fileName = gr.getValue('file_name') + '_' + gr1.number;
				fileName =  gr1.number + '_' + gr.getValue('file_name');
        
            var bin = new GlideSysAttachment().getBytes(gr);
            var entry = new Packages.java.util.zip.ZipEntry(fileName);
           // gs.log('Harika Helper21 ' + entry);
            zipOut.putNextEntry(entry);
            zipOut.write(bin, 0, bin.length);
            zipOut.closeEntry();
        }
	}
        zipOut.close();
        return GlideStringUtil.base64Encode(byteStream.toByteArray());

    },
    type: 'AttachmentZipHelper'
});

View solution in original post

11 REPLIES 11

ddd
Tera Contributor

I tried your method and it worked very well!
However, if downloading in bulk and reaching a certain quantity, there may be a situation where the compressed folder cannot be opened.
Is there a good solution to this?
I suspect that there are too many files to download accurately. 700 pieces is no problem. More than 700 items will have problems.

Hi Harika,

This worked perfectly for my requirement and I was able to increment the file numbering as I also had records with duplicate file names. 

Thanks for posting...greatly appreciated...Lynne