Download the content of a number of attachments via javascript

I have problem on downloading the content of some attachment files, via JavaScript, on my VisualForce Page. To be specific, I think I need a way to pass the content of the attachment in the appropriate way.

I’ve been consulted with this article http://viralpatel.net/blogs/create-zip-file-javascript/, but I need a more dynamic way to pass the content of the attachments, to the JSZip add() method.

To help in better orientation, I am posting my controller and VF page code:

Controller:

public with sharing class FlussiColDownloadZipCTRL {

public string queryAttach;
public string contenutoOutput{get;set;}
public List<Attachment> myAttach;
public Map<String, String> AttachCollection{get;set;}

public Set<String> nomiFile {get;Set;}
public List<String> contenutoFile{get;set;}

//costruttori
public FlussiColDownloadZipCTRL(){
    queryAttach = 'Select id, Name, body From Attachment Limit 1'; 
     AttachCollection = new Map<String, String>();

    nomiFile = new Set<String>();
    contenutoFile = new List<String>();
}

// chiedi i attachment dal DB
public List<Attachment> getAttachments(){

    if(myAttach == null){
        myAttach = new List<Attachment>();
        myAttach = Database.query(queryAttach);

        // Lavora il contenuto dei attachment
        for(attachment a: myAttach){
            List<List<String>> content = new List<List<String>>();
            content = CSVParser.parseCSV(String.valueOf(a.body));

            AttachCollection.put(a.name, strCont);// I am maping ech file name with its content

        }    

        nomiFile = AttachCollection.keySet();
        contenutoFile = AttachCollection.values();            

        return myAttach;
    }
    else
        return myAttach;
}

}

My VF Page:

<apex:page controller="FlussiColDownloadZipCTRL">

<SCRIPT>  
 // funzione per scaricare un file.zip

function create_zip(){
    var zip = new JSZip();
    alert('{!contenutoFile} \n {!NomiFile}');

    zip.add("{!NomiFile}", "{!contenutoFile}");
    zip.add("hello1.txt", "Hello First World\n");
    zip.add("hello2.txt", "Hello Second World\n"); 
    content = zip.generate();
    location.href="data:application/zip;base64," + content;
} 
</SCRIPT>
<apex:form >
    <apex:includeScript value="{!$Resource.jSzip}"/>

    <apex:outputText >Note: Pagna Soto Costruzione.</apex:outputText>
    <apex:pageblock >
        <apex:pageBlocktable value="{!attachments}" var="a">
            <apex:column value="{!a.id}" headerValue="Id "/>
            <apex:column value="{!a.name}" headerValue="Nome attachment"/>
        </apex:pageBlocktable>

        <apex:pageBlockButtons >
            <input type="button" onclick="create_zip()" value="Create Zip"></input>
        </apex:pageBlockButtons>

    </apex:pageblock>
</apex:form>
</apex:page>

Thanks in advance guys!
Cheers,
Endrit.

Answer

One way of doing this, is to retrieve the Attachments with a RemoteAction operation over a List of attachment Ids:

public String getAttachmentIds() {
    //SOQL query
    //Serialize the key set as JSON
}

@RemoteAction
public static List<AttachmentWrapper> getAttachments(List<Id> attachmentIds) {
    //SOQL query for filename and body
    //return base64 encoded body and filename in a list of AttachmentWrapper objects
}

The page needs to call the action and stuff the body and filename into JSZip:

var attachmentIds = JSON.parse('{!JSENCODE(attachmentIds)}');

Visualforce.remoting.Manager.invokeAction(
    '{!$RemoteAction.Controller.getAttachments}',
    getNextSetOfAttachmentIds(),
    function(result, event){
        for (var key in result) {
            if (result.hasOwnProperty(key)) {
                //stuff attachment into JSZip
            }
        }
    }
);

The key is to partition the set of attachment Ids and not retieving all at once, since this will likely hit some limits.

Attribution
Source : Link , Question Author : Endrit Sino , Answer Author : Alexander Johannes

Leave a Comment