Anyone have an example of how to download Salesforce Files from a VF page?

From a custom Contact page detail, I want a button to open a VF page interface to allow a user to select Salesforce Files associated with the Contact to download to the local file system.

| improve this question | | | | |
  • 3
    How is this different from your question 2 hours ago? – Derek F May 9 '18 at 18:12
  • Fair enough. I thought it would make sense to have more concise questions. The Files related list cannot be changed so the advice was to make it a detail page button. So now this question is specifically looking for a VF snippet on how to download Salesforce Files. Perhaps I made the previous question from 2 hours ago too broad. – SkipVV May 9 '18 at 18:17
  • Got it. I posted my comment before I read through and understood your previous question. The titles are very similar, so I short-circuited and jumped to a conclusion (mea culpa). – Derek F May 9 '18 at 18:39
  • Yeah. No worries. I'll try to be more specific in the future. – SkipVV May 9 '18 at 18:48
  • How are your files related to the contact? Via a ContentDocumentLink? – battery.cord May 9 '18 at 19:39

So Salesforce Files are really ContentDocument's under the hood. You'll need a page to fetch the related files for your contact, and provide some information about them (name, file name, file type, etc) in a apex:pageBlock or the lightning equivalent.

On the related object ContentDistribution, which is created when you "publish" a ContentVersion, there are these fields: DistributionPublicUrl, ContentDownloadUrl. These objects & fields depend on some processes (I was making sure a ContentDistribution was available for each version & that each would always return the latest version), but these fields can be used to get download urls for a given file, through a lot of soql (three layers). This is probably only necessary if the other method I mention below doesn't work, but if your serving internal users, you should be fine.

You'll need to query your records, and that should look something like this:

SELECT Id, Title, OwnerId, FileType FROM ContentDocument WHERE ID IN (SELECT ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId IN :ContactIdList)

You can probably get away by using this download link instead using the ones provided by ContentVersion or ContentDistribution:


I took it right off the ContentDocument page. If you have a list of documents on a page, inside something with a loop (apex:pageBlock or apex:repeat), you could do something like this:

<apex:repeat var="doc" value="{!Documents}">
    <a href="https://c.<instance>.content.force.com/sfc/servlet.shepherd/version/download/{!doc.Id}" download="{!doc.Title}">Download</a>

If anything, you might need to provide some extra info about what file type is being downloaded, but this should work otherwise.

| improve this answer | | | | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.