For the past two weeks, CodeLive has been focused on using Salesforce Files. Whether it’s generating invoice pdfs, or manipulating images, knowing how to use files is an important skill for Salesforce Developers. If you missed the live sessions, don’t fret; you can view them on demand here: Part 1, Part 2.
Understanding the object model
Salesforce Files has a number of objects backing its features. First and foremost, is the
ContentVersion object. This is the object that actually stores the contents of the file.
ContentVersion records belong to a single
ContentDocument record, however, a
ContentDocument record has 1..N
ContentVersion records associated with it. This allows you to upload, or create a number of file versions.
ContentDocumentLink records associate
ContentVersion records with other sObject records. For instance, if you want a newly created invoice pdf to appear in the Files related list of an Opportunity, you need to create a
ContentDocumentLink record specifying the
LinkedEntityId (OpportunityId) and the
ContentVersionId (the version of the file you want associated). Finally, creating a
ContentDistribution object for a
ContentVersion record allows the file to be downloaded, or viewable in a browser by third parties. Below is a simplified UML diagram for these objects:
Creating and linking Files
When it comes to creating a file with Apex, you might assume you’d need to create a
ContentDocument object. But inserting a
ContentDocument fails with a “DML Operation Insert not allowed on ContentDocument.” Instead, creating a document starts with defining a
ContentVersion record. Creating a
ContentVersion record creates a
ContentDocument record if no
ContentDocumentId is specified. While that’s a bit counter intuitive, it does allow for having multiple versions of the same file, based on its
ContentDocumentLink records create that link between a File, and another sObjects’ records. That sObject record can be an
Contact or … any object with Files enabled. Just creating a
ContentVersion record isn’t enough. Without a corresponding
ContentDocumentLink record, the file will exist, but it will never show up in the UI. Thankfully there are a couple of ways of creating those associations. First, is to create a
ContentDocumentLink record. Creating a document link requires specifying the
ContentVersionId, as well as a
LinkedEntityId. Of the two, LinkedEntityId is the one to pay attention to. The
Id you specify here, is the record where the file will show up in the related list. The second way of creating that association is my favorite. When you create a
ContentVersion record you can specify the
FirstPublishLocationId field. If you populate that field with a valid recordId, the system will automatically create a
ContentDocumentLink record for you. Let us take a look at a code snippet that handles the boilerplate code necessary for creating and linking a File.
A couple of quick notes about this code, that I discovered while creating it. The
PathOnClient field is critical. The system determines the
FileType of the document from the
PathOnClient field, which is critical for searching! However, the FileType specified is not a direct match to the files extension. During testing I create a file with a
.docx extension. However, if I searched for a file who’s
.docx, I got zero results. Turns out, the associated FileType is: is ‘WORD_X’. It’s quirky, but the two things to remember are:
- The ContentVersion’s PathOnClient field determines what FileType Salesforce assigns.
- The FileType is not a 1:1 to the file’s extension.
One of the very handy aspects to Files is the ability to share that file with unauthenticated third parties. Meaning you can share a link to the file with that opportunities contacts, without needing to let them login to your org to view it. Similar to linking a file to an associated record, publishing the file is as simple as creating a new record. This is where the
ContentDistribution object comes into play. When you create a
ContentDistribution record, you have several options related to formats and permissions. Look at this method from the Files recipe class that we worked on:
Note the fields starting with
Preferences*. These are your various format and download options. The key field, however, is the
ContentVersionId. Note that it’s a
ContentVersion, not a
ContentDocument. You can, if you’d like create multiple
ContentDistribution records with different permissions associated with the same
What are you going to do with Files?
Salesforce Files is a super flexible solution for storing and sharing everything from images to documents. The data model may be a bit unintuitive at first, but when you understand how the four objects work together the power and flexibility really shines. The question remains, however, now that you know how Files work, how will you use them? What about your company’s business processes can you automate by creating, linking and publishing files?
About the author