2

I'm trying to create a Lightning component that uses a button to make an API call. The response is in Content Disposition form that returns an Excel file. I'd like to be able to have the Excel file begin downloading automatically to a User's local machine when the User clicks the button.

Not sure how to handle the Http Response to pass to the Lightning component to initiate the download. Any help is appreciated.

Lightning Component

<aura:attribute name="recordId" type="String"/>
<aura:attribute name="workbookOption" type="String"/>
<aura:attribute name="downloadLink" type="String"/>

<lightning:card title="Workbook Download">    
        <p class="slds-p-horizontal_large">
            <lightning:select name="selectItem" label="Select a Template" value="{!v.workbookOption}">
                <option value="">None</option>
                <option value="Option1">Agency Screening Workbook</option>
                <option value="Option2">Fannie Mae</option>

            </lightning:select>
            <lightning:button variant="brand" label="Create" onclick="{!c.callOutCtrl}" />

        </p>      
</lightning:card>

Javascript Controller

    ({
    callOutCtrl : function(component, event, helper) {
        var action = component.get("c.getFile");
        action.setParams({
                strOppId : component.get("v.recordId"),
                workbookOption : component.get("v.workbookOption")
        });
        action.setCallback(this, function(response){
            //Need to get returned Excel file from the Controller after making API call
        });

        $A.enqueueAction(action);
    }
})

Apex Controller

public class ExcelHandler {  

    @AuraEnabled
    public static void getFile(String strOppId, String workbookOption) {

        HttpRequest request = new HttpRequest();
        //Make API call

        //Found this online (https://developer.salesforce.com/forums#!/feedtype=SINGLE_QUESTION_SEARCH_RESULT&id=906F0000000AY1qIAG)
        String base64value = EncodingUtil.base64Encode(response.getBodyasBlob());

        //Need to download Excel file on the Lightning Component
    }
}
4

You can use a data URI to download the file:

action.setCallback(this, response => {
  let a = document.createElement('a');
  a.href = 'data:application/vnd.ms-excel;base64,'+response.getReturnValue();
  a.download = 'filename.xls';
  a.click();
});

Note that your function needs to be changed to return a string:

@AuraEnabled
public static String getFile(String strOppId, String workbookOption) {
    // ...
    return EncodingUtil.base64Encode(res.getBodyAsBlob());
}
9
  • Thank you, I'm getting the error below for the return statement: "Method does not exist or incorrect signature: void base64Encode(String) from the type System.EncodingUtil" – Al K Oct 7 '19 at 15:29
  • @MikeR Yes, it should have been getBodyAsBlob(). I've updated this answer to reflect that. – sfdcfox Oct 7 '19 at 15:52
  • Thanks again. I made the changes and when trying to make the API call it returns an error on the Lightning Component: 'Uncaught Error in $A.getCallback() [a.getReturnValue is not a function] Callback failed: apex://WorkbookHandler/ACTION$getFile' Seems to be associated with the line ‘a.download = filename.xlsx’. I tried changing the file extension to other related Excel formats but no luck. Appreciate your help with this. – Al K Oct 7 '19 at 16:22
  • @MikeR Nope, sorry, it was another typo on my part. This (hopefully) final edit should fix the problem. – sfdcfox Oct 7 '19 at 18:52
  • OK, it appears to be working but using Google Chrome I can't seem to get the file to download. The download fails with a 'Network Error' in the download bar. The Chrome network feed does not show that anything was returned. If I use Execute Anonymous it shows a successful API call returning the Blob. Seems to be the last step in trying to get this to work but I can't figure it out. Thanks – Al K Oct 7 '19 at 19:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.