Contact Us
Case Studies

How to unzip files in Salesforce?

Many developers know, that there is no native zip support in Apex right now. Actually, there is native zip support in Apex, but for many it will not work. When I told about native zip support, I mean using Static Resources.

Static resources allow you to upload content that you can reference in a Visualforce page, including archives (such as .zip and .jar files), images, style sheets, JavaScript, and other files.

So in effect Salesforce does have a built in Zip handler, at least for unzipping files anyway. You can use Static Resources to unzip needed files. Here is an example how it works. We will use another approaches.

We will use Zippex or JSZip.

Using Zippex for unzipping files

Zippex — native Apex Zip utility for the salesforce.com platform. If you want to work with zip files in Apex, then your choice is this utility.

For example, you get the zip file in Apex using API response:

                        Http http = new Http();
                        request.setTimeout(60000);
                        HttpRequest request = new HttpRequest();
                        request.setEndpoint(endpoint); // your endpoint
                        request.setMethod(method); // your method 'POST'
                        request.setHeader('Content-Type', 'application/json');
                        request.setHeader('Content-Length', String.valueOf(body.length()));
                        if (body != null) {
                        request.setBody(body); // your body
                        }
                        HttpResponse response = http.send(request);
                        Blob myBlob =  response.getBodyAsBlob();
                    

You should use getFile(fileName) method, which extracts the specified file contents from the current Zip archive. If the file does not exist, returns null.

                        Blob myBlob =  response.getBodyAsBlob(); //your zip file
                        Zippex myZip = new Zippex(myBlob);
                                            
                        //Loop through the files in Zip and process them
                        for (String fileName : myZip.getFileNames()) {
                                            
                            Blob fileData = myZip.getFile(fileName); // needed file
                                            
                            //Process fileData here.
                                            
                        }
                    

Unfortunately, getFile() method this utility didn’t work for my zip file, because the file was very big (83kB). I’m getting ‘Apex CPU time limit exceeded’ error when I’m try to getFile() in a loop. And this issue was not only for me. But if you raise the limits using asynchronous Apex (for example, future method), it will work! So let’s move on to the next approach.

Using JSZip for unzipping files

JSZip is a javascript library for creating, reading and editing zip files, with a lovely and simple API.

So, you need to connect JSZip to your org. I decided to upload this library into Static resources. Then I connected my LWC to JSZip:

                        //here jszip is a name of static resource (I uploaded .js file, but not .zip)
                        import jszip from '@salesforce/resourceUrl/jszip';
                        import { loadStyle, loadScript } from 'lightning/platformResourceLoader'; 
                    

To import a third-party JavaScript or CSS library, use the platformResourceLoader module. Load the library and call its functions in a promise then() method:

                        loadScript(this, jszip).then(() => {
                            let newZip = new JSZip()
                            newZip.loadAsync(result, { base64: true })
                                .then((zip) => {
                                    Object.keys(zip.files).forEach((filename) => {
                                        if (filename === 'Needed file.pdf') {
                                            zip.files[filename].async('uint8array').then((fileData) => {
                                                // I get needed file. fileData is Uint8Array
                                                this.passFileToApex(fileData, filename)
                                            })
                                        }
                                    })
                                })
                                .catch((error) => {
                                    this.dispatchEvent(
                                        new ShowToastEvent({
                                            title: 'Error',
                                            message: 'File fetching problem',
                                            variant: 'error',
                                            mode: 'pester',
                                        })
                                    )
                                    console.log('error = ', error)
                                })
                        })
                    

I need to clarify line 3 newZip.loadAsync(result, {base64:true}). I pass from Apex a collection of binary data (Blob) to LWC with an unencoded String:

                        return EncodingUtil.base64Encode(response.getBodyAsBlob());
                    

So I have to specify my zip file (result) and the datatype {base64:true}. I get needed file in 9 line and pass it to passFileToApex method of LWC:

                        passFileToApex(fileData, filename) {
                            let id = this.recordId;
                            let blob = new Blob([fileData], {type: 'application/pdf'});

                            let reader = new FileReader();
                            reader.readAsDataURL(blob);
                            reader.onloadend = () => {

                                sendNeededFile({
                                    file: rader.result,
                                    id: id,
                                    name:filename
                                })
                                .then(result => {
                                    if (result === 'sent') {
                                        this.dispatchEvent(
                                            new ShowToastEvent({
                                                title: 'Success',
                                                message: 'This email was sent successfully',
                                                variant: 'success',
                                                mode: 'pester'
                                            })
                                        )
                                    }
                                })
                                .catch(error => {
                                    this.dispatchEvent(
                                        new ShowToastEvent({
                                            title: 'Error',
                                            message: 'The email sending failed.',
                                            variant: 'error',
                                            mode: 'pester'
                                        })
                                    );
                                });
                            }
                        }                    
                    

I get Blob in line 3 and convert it to unencoded String to pass to Apex method sendNeededFile. In Apex method I send email user with attachment (Needed file.pdf).

Conclusion

We’ve covered three approaches to unpacking a file in Silesforce. We have just outlined the first approach (using Static resources). The second approach (Zippex) is suitable for small archives. Well, we’ve taken a closer look at the third approach (JSZip). In our case, he turned out to be a worker. Good luck in coding!

Contact Us

If you have any questions left, feel free to contact us, we are always nearby :