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

9 REPLIES 9

Hi,

I wanted to append record number to file name because we have duplicate filenames and it gives me an error.

HarikaThota_3-1746625543397.png

 

I wanted to add to the highlighted part.

This is the error I got when I tried to add record number to it:

HarikaThota_4-1746625543387.png

 

Thanks,

Harika

@Harika Thota 

how does your script handle adding the record number?

Can you share what's your exact business requirement?

From where are you triggering that code of UI action?

where is that zip stored? on some record? since your image is for windows laptop are you pushing that zip?

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

Hi Ankur,

 

I'm triggering them from the list view of the table and when I select the records and click on the UI Action it has to download the attachments of the records.

 

It was working well but if the attachments have duplicate file names eg:image001.jpg in WM000001 & image001.jpg in WM000002 as well. 

SO i cannot remove the duplicates because file name might be duplicate but not the content so I thought of appending record number to the file name.

I would need help in modifying the code to append record number to file names eg: image001_WM00001 when downloaded to zip.

dougmoto
Tera Contributor

My reply from yesterday doesn't seem to be showing up, but if you look in the "zipSelectedAttachments" function here:

 

var entry = new Packages.java.util.zip.ZipEntry(gr.getValue('file_name'));

 

this is where the file name is being added to the files before its added to zip file, it's taking the name from "gr.getValue('file_name')" so you can append an incremented number before you add to zip:

 

var entry = new Packages.java.util.zip.ZipEntry(gr.getValue('file_name') + "_" + i);

i++;

 

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'
});