Displaying Salesforce Files in LWC is a common requirement when building custom record pages, document management solutions, customer onboarding applications, and approval processes. While Salesforce provides a standard Files related list, developers often need more control over how files are displayed, filtered, previewed, or downloaded.
The challenge is that Salesforce Files are not stored directly on records. Instead, Salesforce uses a file architecture built around ContentDocument, ContentVersion, and ContentDocumentLink objects. Understanding how these objects work together is essential before building any custom file viewer in Lightning Web Components.
In this guide, you’ll learn how to query Salesforce Files using Apex, display them inside an LWC component, show file details in a Lightning Datatable, and implement file preview and download functionality using best practices.
What Are Salesforce Files?
Before writing any code, it’s important to understand what Salesforce Files actually are.
Many new developers assume files are stored directly against records. However, Salesforce uses a centralized content management system that allows a single file to be associated with multiple records.
For example, a contract PDF uploaded to an Account can also be linked to related Opportunities, Cases, or custom objects without creating duplicate copies.
This architecture improves storage efficiency and makes file management much more flexible.
Today, Salesforce Files have largely replaced the older Notes & Attachments model, which offered fewer capabilities and limited sharing options.
Understanding the Salesforce Files Data Model
Whenever you query Salesforce Files in LWC, you’ll typically work with three important objects.
ContentDocument
ContentDocument represents the file itself.
Think of it as the parent record that remains constant even when new versions of the file are uploaded.
Every Salesforce File has one ContentDocument record.
Example:
Contract.pdf
↓
ContentDocument
ContentVersion
ContentVersion stores a specific version of a file.
Whenever a user uploads a newer version of a document, Salesforce creates a new ContentVersion record while keeping the same ContentDocument.
Example:
Contract V1
Contract V2
Contract V3
↓
ContentVersion Records
Common fields include:
- Title
- FileExtension
- VersionNumber
- VersionData
- ContentDocumentId
ContentDocumentLink
ContentDocumentLink connects files to Salesforce records.
Without this object, Salesforce wouldn’t know which Account, Opportunity, Contact, or custom object should display the file.
Example:
Account
↓
ContentDocumentLink
↓
ContentDocument
This object is usually the starting point when querying files related to a specific record.
How Salesforce Files Are Connected
The relationship looks like this:
Record
↓
ContentDocumentLink
↓
ContentDocument
↓
ContentVersion
Understanding this relationship is the key to building custom file components successfully.
Most file-related development work follows this exact path.
Real-World Use Cases for Salesforce Files in LWC
Many projects require more than the standard Files related list.
Some common examples include:
- Customer document portals
- Contract management systems
- Insurance claim uploads
- Vendor onboarding applications
- Loan processing solutions
- Employee document management
In one project, I needed to display only signed contracts attached to an Opportunity. The standard Files related list displayed every uploaded file, which created confusion for users.
A custom LWC component solved the problem by filtering and displaying only contract documents while hiding unrelated files.
How to Query Salesforce Files in LWC
Lightning Web Components cannot directly perform SOQL queries.
To retrieve Salesforce Files, you’ll first create an Apex controller.
The process usually works like this:
LWC
↓
Apex Controller
↓
ContentDocumentLink
↓
ContentVersion
↓
Return File Data
The Apex controller queries Salesforce data and sends the results back to the component.
If you’ve previously worked with record forms, you’ll notice a similar server-to-client pattern How to Use lightning-record-edit-form in Salesforce LWC , although file retrieval requires custom Apex.
Creating the Apex Controller
The first step is retrieving files related to a specific record.
FileController.cls
public with sharing class FileController {
@AuraEnabled(cacheable=true)
public static List<ContentVersion> fetchFiles(Id recordId) {
List<ContentDocumentLink> links = [
SELECT ContentDocumentId
FROM ContentDocumentLink
WHERE LinkedEntityId = :recordId
];
Set<Id> documentIds = new Set<Id>();
for(ContentDocumentLink link : links){
documentIds.add(link.ContentDocumentId);
}
return [
SELECT Id,
Title,
FileExtension,
ContentDocumentId,
CreatedDate
FROM ContentVersion
WHERE ContentDocumentId IN :documentIds
AND IsLatest = TRUE
];
}
}
This code performs two important operations:
- Retrieves linked file IDs from ContentDocumentLink.
- Retrieves the latest ContentVersion records.
Using IsLatest = TRUE ensures that users always see the newest version of a file.
Why Use Cacheable Methods?
Notice this annotation:
@AuraEnabled(cacheable=true)
This improves performance significantly.
Because file data doesn’t change every second, Salesforce can temporarily cache the response and reduce server calls.
Benefits include:
- Faster page loads
- Reduced Apex execution
- Better user experience
- Lower server overhead
Whenever you’re displaying read-only file information, cacheable methods are usually the best choice.
Creating the Lightning Web Component
Once Apex returns the data, the next step is displaying it inside a component.
fileViewer.js
import { LightningElement, api, wire }
from 'lwc';
import fetchFiles
from '@salesforce/apex/FileController.fetchFiles';
export default class FileViewer extends LightningElement {
@api recordId;
files;
error;
@wire(fetchFiles, { recordId: '$recordId' })
wiredFiles({ error, data }) {
if(data){
this.files = data;
}
else if(error){
this.error = error;
}
}
}
This component automatically retrieves files whenever the page loads.
The @wire service keeps the code clean and eliminates manual server calls.
Displaying Salesforce Files in LWC
After retrieving file data, you can render it in the HTML template.
fileViewer.html
<template>
<lightning-card title="Related Files">
<template if:true={files}>
<template
for:each={files}
for:item="file">
<div
key={file.Id}
class="slds-box">
<p>{file.Title}</p>
</div>
</template>
</template>
</lightning-card>
</template>
This creates a simple file list showing file names.
Although basic, it’s a great starting point before adding advanced functionality like previews and downloads.
Handling Errors Gracefully
Production components should always handle failures properly.
For example:
- User lacks access
- Record contains no files
- Apex exceptions occur
- Network interruptions happen
Displaying friendly messages improves usability.
You can also show toast notifications when errors occur. We used a similar approach in How to Show a Toast Message in Salesforce LWC, which helps users immediately understand what went wrong.
Common Mistakes When Querying Salesforce Files
Many developers encounter issues because they misunderstand Salesforce’s file architecture.
Some common mistakes include:
Querying ContentVersion Directly
Without first identifying linked documents, you may retrieve unrelated files.
Forgetting IsLatest
This can display outdated versions of documents.
Retrieving Too Many Fields
Large payloads slow down component performance.
Ignoring Sharing Rules
Users should only see files they are authorized to access.
Querying Thousands of Files
Large result sets can impact performance significantly.
Using selective queries and pagination becomes important as file volume grows.
How to Display Salesforce Files in a Lightning Datatable
Displaying files in a simple list works well for basic requirements, but most enterprise projects require a more structured interface.
A Lightning Datatable provides a better user experience because users can quickly view file names, file types, creation dates, and download options in a tabular format.
fileViewer.js
columns = [
{
label: 'File Name',
fieldName: 'Title'
},
{
label: 'Type',
fieldName: 'FileExtension'
},
{
label: 'Created Date',
fieldName: 'CreatedDate',
type: 'date'
}
];
fileViewer.html
<lightning-datatable
key-field="Id"
data={files}
columns={columns}>
</lightning-datatable>
This approach becomes especially useful when records contain dozens of files.
If you’re new to datatables, the implementation is very similar to the techniques covered in How to Display Data in a Lightning Datatable in LWC
How to Download Salesforce Files in LWC
One of the most common requirements is allowing users to download files directly from a component.
Fortunately, Salesforce already provides download URLs.
Updating Apex Query
SELECT Id,
Title,
FileExtension,
ContentDocumentId
FROM ContentVersion
WHERE ContentDocumentId IN :documentIds
AND IsLatest = TRUE
Creating Download URLs
this.files = data.map(file => {
return {
...file,
downloadUrl:
'/sfc/servlet.shepherd/version/download/' +
file.Id
};
});
HTML
<template for:each={files} for:item="file">
<div key={file.Id}>
<a
href={file.downloadUrl}
target="_blank">
Download
</a>
</div>
</template>
When users click the link, Salesforce automatically downloads the selected file.
This solution works well for PDFs, Word documents, images, spreadsheets, and other supported file types.
How to Preview Salesforce Files in LWC
Downloading files isn’t always ideal.
Many users prefer previewing documents before deciding whether to download them.
Salesforce provides native file preview functionality through NavigationMixin.
filePreview.js
import { NavigationMixin }
from 'lightning/navigation';
export default class FileViewer extends
NavigationMixin(LightningElement) {
openPreview(event) {
const documentId =
event.target.dataset.id;
this[NavigationMixin.Navigate]({
type: 'standard__namedPage',
attributes: {
pageName: 'filePreview'
},
state: {
selectedRecordId:
documentId
}
});
}
}
HTML
<lightning-button
label="Preview"
data-id={file.ContentDocumentId}
onclick={openPreview}>
</lightning-button>
This opens Salesforce’s native preview window, providing a familiar experience for users.
How to Search Salesforce Files by Name
As the number of files grows, users often need a search feature.
For example:
- Search contracts
- Search invoices
- Search proposals
- Search onboarding documents
A simple search box can significantly improve usability.
HTML
<lightning-input
label="Search Files"
onchange={handleSearch}>
</lightning-input>
JavaScript
searchKey = '';
handleSearch(event) {
this.searchKey =
event.target.value;
}
Apex Query
SELECT Id,
Title
FROM ContentVersion
WHERE Title LIKE :('%' + searchKey + '%')
AND IsLatest = TRUE
This enables users to locate files quickly without scrolling through long lists.
Using a Wrapper Class for Better Performance
Many developers return complete ContentVersion records directly to the client.
While this works, it’s not always the best approach.
A wrapper class allows you to return only the fields your component actually needs.
Wrapper Class
public class FileWrapper {
@AuraEnabled
public String title;
@AuraEnabled
public String type;
@AuraEnabled
public Id documentId;
}
Benefits include:
- Smaller payloads
- Faster performance
- Better maintainability
- Cleaner code
For large-scale implementations, wrapper classes are usually recommended.
ding Pagination for Large File Lists
Some Accounts or Opportunities may contain hundreds of files.
Loading everything at once can impact performance.
A better approach is pagination.
Example:
LIMIT 20
OFFSET 0
Then load additional records when users click Next.
Benefits include:
- Faster page load
- Better performance
- Improved user experience
- Reduced server load
Pagination becomes especially important in document-heavy industries such as insurance, healthcare, and finance.
Best Practices for Displaying Salesforce Files in LWC
After working on multiple file management projects, these practices consistently produce better results.
Always retrieve only the fields you need.
Avoid querying every file version when users only need the latest document.
Use cacheable Apex methods whenever possible.
Implement file previews instead of forcing downloads.
Use datatables for records containing many files.
Apply pagination when large datasets are expected.
Test with different user profiles to ensure sharing rules behave correctly.
Finally, avoid hardcoding URLs and IDs whenever possible.
Real Project Experience
I first built a custom Salesforce Files component for a contract management application where users needed quick access to signed agreements stored against Opportunities.
Initially, the standard Files related list was used. However, users struggled to find the correct documents because hundreds of files were attached to each record.
We created a custom LWC that queried ContentDocumentLink records, displayed only signed contracts, and added preview and download actions. The result was a much cleaner interface and significantly faster document retrieval for the sales team.
Frequently Asked Questions
How do I query Salesforce Files in LWC?
Use an Apex controller to query ContentDocumentLink and ContentVersion objects, then return the results to Lightning Web Components.
What is ContentDocument in Salesforce?
ContentDocument represents the main Salesforce File record and acts as the parent for all file versions.
What is ContentVersion?
ContentVersion stores a specific version of a Salesforce File.
What is ContentDocumentLink?
ContentDocumentLink connects Salesforce Files to records such as Accounts, Contacts, Opportunities, and custom objects.
Can I preview Salesforce Files in LWC?
Yes. You can use NavigationMixin to open Salesforce’s native file preview window.
Can I download files from LWC?
Yes. Salesforce provides download URLs through the Shepherd servlet.
Should I query ContentVersion directly?
Usually no. Most implementations first query ContentDocumentLink to identify related files.
How do I show files in a Lightning Datatable?
Retrieve file data from Apex and bind it to a lightning-datatable component.
How do I search Salesforce Files?
Use a search box and filter ContentVersion records using a SOQL LIKE condition.
Can I use Salesforce Files in Experience Cloud?
Yes. Salesforce Files can be displayed in Experience Cloud sites when users have the necessary permissions.
Conclusion
Understanding How to Query and Display Salesforce Files in LWC is essential for building document-centric Salesforce applications. By using ContentDocument, ContentVersion, and ContentDocumentLink correctly, developers can retrieve file information efficiently and present it through custom Lightning Web Components.
Whether you’re displaying related files, building a contract management solution, adding file previews, or enabling downloads, a well-designed LWC provides far more flexibility than the standard Files related list. By following the techniques and best practices covered in this guide, you can create scalable, user-friendly file management experiences that perform well even in large Salesforce environments.