How to create and download a dynamic file in Salesforce without storing in Salesforce files

Author: Bruce Tollefson Published: April 20, 2021; Modified: May 9, 2022
lightning_bolts

There are multiple ways to create files within Salesforce. Most lead to creating the file and storing in Salesforce files. In many instances this is the proper solution. However there are times when you need to create a file in Salesforce that either is a one time use and/or needs to continuously be updated from a record’s values.

In turn this can create a couple of challenges primarily with having to store and update the files each time there is a change. And if there is PII or HIPAA data then there are additional considerations that need to be had with those files. As an alternative here is a way you can create dynamically create a file in Salesforce, automatically download the file, and not have to worry about storing the file.

In order to achieve this goal we will be using a Lightning Web Component that uses the encodeURIComponent(), the Data URLs, the download attribute in an anchor tag, and the LWC wire service. We will create a component placed on the account record page that has a link, when clicked this link will download a text file that has the Account name in the file and file name. Using the wire service each time the account name changes the file will also change.

Dynamic File Downloader Lightning Web Component

HTML

Create a shell <a> tag that will dynamically have attributes added.

<template> <lightning-card class="slds-text-align_center"> <a></a> </lightning-card> </template>

Javascript

Launch the wire service to get the Account Name then get the <a> element and add the text file and download attribute.

import { LightningElement, wire, api } from 'lwc'; import { getRecord} from 'lightning/uiRecordApi'; export default class TextFileLauncher extends LightningElement { @api recordId; text = ''; @wire(getRecord, { recordId: '$recordId', fields: ['Account.Name'] }) account({ error, data }) { if (data) { //create a tag attributes and file let recordName = data.fields.Name.value; this.text = `data:text/plain,${encodeURIComponent(`Hello ${recordName}`)}`; let anchorTag = this.template.querySelector('a'); anchorTag.setAttribute('href',this.text); anchorTag.setAttribute('download', recordName); anchorTag.innerText = 'Click for Text File!'; } else if (error) { console.log(error); } }; }

Meta.xml

This is the standard meta to put on the account.

<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>51.0 <isExposed>true <targets> <target>lightning__RecordPage </targets> </LightningComponentBundle>

As we can see from below once you click on the link the file will download.

After updating the record account name and clicking the link again a new file with the name change has been created.

8 comments on “How to create and download a dynamic file in Salesforce without storing in Salesforce files”

  • Garrepalli Kumar says:

    [LWC component’s @wire target property or method threw an error during value provisioning. Original error:
    [Cannot read properties of undefined (reading ‘value’)]]

    I am getting this error

  • Mitchell Cook says:

    Is there a way to make the method call the same way as with the <a> tag but using a button? It is not working for me when I replace the <a> with the button id that I want to use.

    • You should be able to on the button onclick build the link and then use the .click() method once the link is built. However I would use the <a href="https://www.lightningdesignsystem.com/components/buttons/#Button-vs.-Link" rel="nofollow ugc">slds button class</a> and turn the link into a visual button

  • Mitchell Cook says:

    How can I modify this to print out more than one field to the text file? I am trying to generate a text file with multiple field values and to format it in a certain way.

    • If you are trying to get more field values and create a longer message. You can change the value in the encodedURIComponent to a variable and pass that in from the Javascript. Then the wire could get more field values and you create the string you are looking to build. If you are looking to make it more dynamic where you need to pass in a value you can create an input field, call an apex method from the wire, and then either have the string output of the wire be the final value needed or add logic in the Javascript after the wire to make any necessary changes.

  • William Aldana says:

    for me works changing Js line 15 to:

    this.text = ‘data:text/plain,’ + encodeURIComponent(‘Hello ${recordName}’);

  • Leave a Reply

    Your email address will not be published. Required fields are marked *