6

I'm trying to show a button on a Lightning Web Component, that when clicked generates a PDF and immediately starts downloading it on the browser. The LWC lives in a Screen Flow and I'm currently triggering it using Flow Debug.

Currently when I click the button nothing happens and nothing appears in the logs. What am I missing here? Thanks!

The relevant files are:

printJobsContainer.html:

    <template>
       <lightning-button label="Generate PDF" onclick={generatePdf}></lightning-button>
     </template>

printJobsContainer.js:

    import { LightningElement } from 'lwc';
    import downloadPDF from '@salesforce/apex/PrintJobPDFController.downloadPDF';

    export default class PrintJobsContainer extends LightningElement {
   
      generatePdf(event){
        downloadPDF
      }
    }

PrintJobPDFController.cls

    public with sharing class PrintJobPDFController {
 
      public static Boolean downloadPDF() {
        // Was hoping this would trigger the download to start
        Page.envelopes.getHeaders().put('content-disposition', 'attachment; filename=envelope.pdf');
        return true
      }
    }

envelopes.page:

     <apex:page renderAs="pdf" applyHtmlTag="false" showHeader="false" cache="true" readOnly="true">
     <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
            <style>
                @page {
                    size: a4 portrait;
                }            
            </style>
        </head>
        <body>
            <h1>Test to see if this will generate</h1>
        </body>
    </html>
    </apex:page>

2 Answers 2

10

You can use download.js to implement this functionality. The main idea is to convert the PDF into Base64 encoded String and pass it to the download method of download.js. Which will show the file download window upon the same screen.

I tried to modify your code as below and it is working.

printJobsContainer.html

    <template>
        <lightning-card title="Download PDF">
            <lightning-layout>
                <div class="slds-p-around_small" >
                    <lightning-button variant="brand" label="Generate PDF" onclick={generatePdf}></lightning-button>
                    <br/><br/>
    
                    <template if:true={boolShowSpinner}>
                        <lightning-spinner alternative-text="Loading" size="large"></lightning-spinner>
                    </template>
    
                </div>
            </lightning-layout>
        </lightning-card>
    </template>

printJobsContainer.js

    import { LightningElement, wire } from 'lwc';
    import { loadScript } from 'lightning/platformResourceLoader';
    import downloadjs from '@salesforce/resourceUrl/downloadjs';
    import downloadPDF from '@salesforce/apex/PrintJobPDFController.getPdfFileAsBase64String';
    
    export default class PrintJobsContainer extends LightningElement {
        boolShowSpinner = false;
        pdfString;
        generatePdf(){
            this.boolShowSpinner = true;
            downloadPDF({}).then(response => {
                console.log(response);
                this.boolShowSpinner = false;
                var strFile = "data:application/pdf;base64,"+response;
                window.download(strFile, "sample.pdf", "application/pdf");
    
            }).catch(error => {
                console.log('Error: ' +error.body.message);
            });
        }
        renderedCallback() {
            loadScript(this, downloadjs)
            .then(() => console.log('Loaded download.js'))
            .catch(error => console.log(error));
        }        
    }

PrintJobPDFController.cls

    public with sharing class PrintJobPDFController {
        @AuraEnabled 
        public static String getPdfFileAsBase64String() {
            PageReference pdfPage = Page.envelope;
            Blob pdfBlob = pdfPage.getContent();
            String base64Pdf = EncodingUtil.base64Encode(pdfBlob);
            return base64Pdf;
        }
    }

envelope.page

    <apex:page renderAs="pdf" applyHtmlTag="false" showHeader="false" cache="true" readOnly="true">
        <html>
            <head>
                <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
                <style>
                    @page {
                    size: a4 portrait;
                    }            
                </style>
            </head>
            <body>
                <h1>Test to see if this will generate</h1>
            </body>
        </html>
    </apex:page>

Screengrab

enter image description here

I have posted a similar solution with Aura Component earlier.

5
  • Please mark it if answered you question !!!
    – Saroj Bera
    May 7, 2021 at 3:30
  • Thanks for the great response with a working example Saroj!
    – Dan
    May 7, 2021 at 7:04
  • 1
    Great answer. Works with FileSaver.js Oct 4, 2021 at 16:30
  • 1
    This is a great answer! I was able to quickly adjust for my use case and it works amazingly. For anyone curious. I did this with a file already in the CRM. We need to be able to map files to users and libraries don't work for us, so we use apex to map it and this allows the download. Nov 8, 2021 at 20:09
  • This solution doesn't work in mobile device
    – Alex M.
    Feb 28, 2022 at 10:59
0

In your printJobsContainer.js file it should be downloadPDF() not just downloadPDF.

And for just downloading the pdf file you don't need to call Apex Controller, you can simply change your js function like

   generatePdf(event){
    var url = '/apex/envelopes';
    window.open(url);
  }

and this will download your pdf.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .