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

Harika Thota
Tera Expert

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 Expert

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

10 REPLIES 10

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.