[SalesForce] How to download files, documents (attachments) in salesforce via apex

I want to download all files associated with records (single or multiple records) of a particular object at one click, using apex.

Let's say that there is a custom object myVehicle which holds information such as – name, number (custom unique number), model, colour, brand, price, country and some attachments in many different formats – word, excel, picture, pdf, etc.

I want to create a visualforce page or similar where when user clicks on a button or link, all attachments of vehicles (not all, but based on filter criteria) gets downloaded. Currently we have achieved following –

An Apex Page –

<apex:outputLink value="{!URLFOR('/sfc/servlet.shepherd/version/download/' & vehIdspage & '?')}" target="_document">Attachments Download</apex:outputLink>

Controller Class –

for(myVehicle__c veh: [select Id,Name,country__c,Number__c from myVehicle__c ]){

    for(ContentDocumentLink conDoc:[SELECT Id,ContentDocumentId ,LinkedEntityId FROM ContentDocumentLink WHERE LinkedEntityId=: veh.Id]){
        for (ContentVersion docVersion : [Select Id, VersionData from ContentVersion where ContentDocumentId =:conDoc.ContentDocumentId ]) {

            string ContentDown= docVersion.Id;
            vehIds = conIds + docVersion.Id +'/';
        }
        vehIdspage=vehIds.removeEnd('/'); 
    }
}

with this code, we are able to download multiple files of one record and multiple files of many records in one zip file. But our data may reach to 5000-10,000 records, and each records may have N number of attachments. Constructing URL for these many records may become too large. And I think there might a limit to it.

Also we want to change title of files before downloading.

So it creates 2 questions –

  1. How can we overcome URL limitation ?
  2. And how can title of files be changed before downloading ?

And final question – is there any other alternatives for downloading files ?

Best Answer

But our data may reach to 5000-10,000 records, and each records may have N number of attachments.

This statement rules out using Apex to provide a single download link for all the related files. There are simply too many to process in a single transaction. You will blow past either your SOQL, Heap, or CPU limits.

Your approach should change based on the final destination for all these files. I'd assume since you are potentially retrieving tens of thousands of files it isn't intended for immediate human consumption.

I'd recommend using the Bulk API from an external system to retrieve the required files. This could be combined with the REST API or Partner API SOQL query to find the required ContentVersion records. If you invert the SOQL query to start from the ContentVersion records you can avoid the need to run one query per ContentDocumentLink.