How to Build File Upload Component in Salesforce LWC

In Salesforce, you often need to add files (like PDFs or pictures) to records . While Salesforce has a standard feature for this, building your own file uploader with a Lightning Web Component (LWC) gives us more control over how it looks and works.

This Salesforcehours guide will help you, step by step, how to create a file uploader that you can use on any record page to make attaching files easy……

Understanding the Component Architecture

Before writing any code, it’s important to understand the overview . Our component’s architecture involves two key parts: a frontend LWC that captures the user interaction and a backend Apex class that processes the data.

  1. File Selection (LWC): A user clicks the input and selects a file from their local machine.
  2. Client-Side Processing (LWC): The component’s JavaScript captures the file and uses the browser’s built-in FileReader API. This powerful tool reads the file’s contents and converts it into a Base64 encoded string—a text representation of the file’s binary data.
  3. Server-Side Call (Apex): The JavaScript then calls a method in our Apex controller, securely passing the Base64 string, the original filename, and the ID of the current record.
  4. Salesforce File Creation (Apex): The Apex method on the server decodes the Base64 string back into its original binary form and performs two critical DML operations:
    • It creates a ContentVersion record, which stores the file data itself.
    • It creates a ContentDocumentLink record to associate the newly created file with the target Salesforce record (e.g., an Account, Contact, or a custom object).

This client-to-server flow is efficient, secure, and aligns with modern Salesforce development best practices.

Step 1: Create the Backend Apex Controller

The first step is to build the Apex class that will serve as the backend for our component. This class contains the logic to receive the file data and create the appropriate records in Salesforce.

Key Salesforce Objects:

  • @AuraEnabled: This annotation is essential. It exposes the apex method, making it accessible to be called from our frontend LWC component.
  • ContentVersion: This SObject represents a specific version of a file stored in Salesforce. When you insert a ContentVersion, Salesforce automatically creates the parent ContentDocument record that represents the file as a whole.
  • ContentDocumentLink: This SObject is the bridge. It links a ContentDocument to a specific record via its LinkedEntityId field, making the file appear in the record’s “Files” related list.

Code : Create a apex class

public class FileUploadController {
  @AuraEnabled
  public static String uploadFile(
      String base64, String filename, String recordId) {
    ContentVersion cv = createContentVersion(base64, filename);
    ContentDocumentLink cdl = createContentLink(cv.Id, recordId);
    if (cv == null || cdl == null) {
      return null;
    }
    return cdl.Id;
  }
  private static ContentVersion createContentVersion(
      String base64, String filename) {
    ContentVersion cv = new ContentVersion();
    cv.VersionData = EncodingUtil.base64Decode(base64);
    cv.Title = filename;
    cv.PathOnClient = filename;
    try {
      insert cv;
      return cv;
    } catch (DMLException e) {
      System.debug(e);
      return null;
    }
  }
  private static ContentDocumentLink createContentLink(
      String contentVersionId, String recordId) {
    if (contentVersionId == null || recordId == null) {
      return null;
    }
    ContentDocumentLink cdl = new ContentDocumentLink();
    cdl.ContentDocumentId = [SELECT ContentDocumentId FROM ContentVersion WHERE
                                 Id = : contentVersionId]
                                .ContentDocumentId;
    cdl.LinkedEntityId = recordId;
    cdl.ShareType = 'V';
    try {
      insert cdl;
      return cdl;
    } catch (DMLException e) {
      System.debug(e);
      return null;
    }
  }
}

Step 2.a: Create a LWC component

Next, we define the structure and user interface of LWC component.

Create a HTML File : Create this file within your LWC’s folder .

<template>
    <lightning-card title="File Upload " icon-name="action:add_file">
        <div class="slds-m-around_medium">
            <lightning-input type="file" accept=".xlsx, .xls, .csv, .png, .doc, .docx, .pdf" label="Attachment"
                onchange={openfileUpload}>
            </lightning-input>
        </div>
        <template if:true={fileData}>
            <p>{fileData.filename}</p>
            <br>
        </template>
        <lightning-button variant="brand" label="Submit" title="Submit" onclick={handleClick}
            class="slds-m-left_x-small">
        </lightning-button>
    </lightning-card>
</template>


Step 2.b: Create LWC JavaScript file

This JS file is the core of our component’s client-side logic. It handles user events, processes the selected file, and communicates with the Apex controller.

import { LightningElement, api } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import uploadFile from '@salesforce/apex/FileUploadController.uploadFile';
export default class FileUploaderCompLwc extends LightningElement {
    @api recordId;
    fileData = null;
    get isUploadDisabled() {
        return !this.fileData;
    }
    openfileUpload(event) {
        const file = event.target.files[0];
        if (file) {
            const reader = new FileReader();
            reader.onload = () => {
                const base64 = reader.result.split(',')[1];
                this.fileData = {
                    filename: file.name,
                    base64: base64,
                    recordId: this.recordId
                };
                console.log('Selected file:', this.fileData);
            };
            reader.readAsDataURL(file);
        }
    }
    handleClick() {
        if (!this.fileData) {
            this.showToast('Please select a file before uploading!', 'error');
            return;
        }
        const { base64, filename, recordId } = this.fileData;
        uploadFile({ base64, filename, recordId })
            .then(() => {
                console.log("filename---->", filename);
                this.showToast(`${filename} uploaded successfully!!`, 'success');
                this.fileData = null; // Reset after successful upload
            })
            .catch(error => {
                this.showToast(`Upload failed: ${error.body?.message || error.message}`, 'error');
            });
    }
    showToast(message, variant = 'info') {
        this.dispatchEvent(new ShowToastEvent({
            title: message,
            variant: variant
        }));
    }
}


Step 2.c: Configure the LWC Xml file

Xml file automatically gets created but we can target where we want to add our component.

<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>63.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__HomePage</target>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>

Deploying and Using Your Component

With Apex class and LWC component created and saved in your local SFDX project, deploy them to your Salesforce org. Once the deployment is successful, you can add the component to any Lightning record page:

  1. Navigate to a record page (e.g., an Account ,Opportunity ).
  2. Click the Setup gear icon and select Edit Page.
  3. In the Lightning App Builder, find your Componnet (“fileUploaderCompLwc”) under the “Custom” section in left side .
  4. Drag the component onto the desired area of the page.
  5. Click Save and Activate.

Final Output

Once deployed and placed on a record page, your will be able to see the component as shown in below image.

File upload component in salesforce LWC

File Selection

When a user selects a file, its name appears below the input field. This confirms their selection before they click the upload button and enables the button for use.

File upload component in salesforce

Successful Upload

After clicking the “Submit” button, a success toast message appears at the top of the screen. The selected file name is cleared, and the component is ready for another upload.

File upload component in salesforce

Alternative Approach: Using the “lightning-file-upload “Base Component

It’s important to note that for many use cases, building a completely custom component is not necessary. Salesforce provides a standard base component, lightning-file-upload, which offers an integrated way for users to upload multiple files. You can configure this component to accept specific file types, and it handles the file processing and attaching automatically without requiring any Apex code.

When to use lightning-file-upload:

  • You need a quick and easy way to allow multiple file uploads.
  • The standard user interface is acceptable for your needs.
  • You don’t need to perform any complex custom logic before or after the file is uploaded.

Do you wanted to Master Your Salesforce LWC Interview with 15 Real-World LWC Scenarios : CLICK HERE

Author

  • komal

    As a 7x Certified Salesforce Professional with over 3 years of hands-on experience in Salesforce Customization and Configuration, I'm a passionate Salesforce enthusiast dedicated to helping businesses leverage the full potential of the platform. My expertise lies in building and optimizing solutions that streamline processes and enhance user engagement.


Discover more from Salesforce Hours

Subscribe to get the latest posts sent to your email.

Leave a Reply

Discover more from Salesforce Hours

Subscribe now to keep reading and get access to the full archive.

Continue reading