Download File : Power Automate and JavaScript

What is Issue?

When working on D365 CRM, Some time user wants to download file from SharePoint, OneDrive or CRM Notes itself. So how you will do it in shortest way?

The Reason-

Downloading file from SharePoint or any other cloud location it will be time consuming process if you choose Web service or any WCF service.

Solution-

Now Power Automate provides less code and quick solutions. Power Automate has all the connectors and Actions which help you to connect these cloud locations and process on the files.

Let’s see a scenario, I want to download a file on button click on my CRM Account form. The file is located in my account record Timeline Notes.

Let’s go step by step.

First of all, as this is action on click of button on form, we can choose “When Http Request Received” trigger in Power Automate. And in HTTP request we need record id i.e. accountid to retrieve specific Note attachment i.e. “CustomerInfoDoc”-

Now from above step we will get the Document – File name and Document body (base64) content.

So we need a variable to store files in array and another variable for document content-

Setting the variables from the Notes list which we got from “List rows” action-

We need to append array with below json-

{
“Name”: @{items(‘Apply_to_each’)?[‘filename’]},
“ContentBytes”: @{items(‘Apply_to_each’)?[‘documentbody’]}
}

We will use Name and ContentBytes in JavaScript Code which will be in the response of HttpRequest.

Now once file we got file content we need to send them in response-

We need the only file from Notes, In List Row action we can add row count =1, but still in response we can set formula in body first(variable(‘ContentArray’). As this is document in response add headers “Content-type”:”multipart/form-data”

Now our complete flow is ready and it looks like –

So now remaining part is calling the flow from button to download the file-

Add the below javascript and call “callPowerAutomateFlow” function on button click. Below is complete code for download –

function callPowerAutomateFlow(formContext) { 
    id = formContext.data.entity.getId().replace("{", "").replace("}", ""); 
    var account = '{ "accountid": "' + id + '"'+ '}'; 
    var flowUrl = "https://prod-04.centralindia.logic.azure.com:443/workflows/xxxxxxxxxxxxxxxxxxxxxxxxxx/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=xxxxxxxxxxxx"; 
 
    var req = new XMLHttpRequest(); 
    req.open("POST", flowUrl, true); 
    req.setRequestHeader("Accept", "application/json"); 
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8"); 
    req.onreadystatechange = function () { 
        if (this.readyState === 4) { 
            req.onreadystatechange = null; 
            if (this.status === 200) { 
                    var result = JSON.parse(this.response); 
                    var fileName = result.Name; 
                    var fileCont = result.ContentBytes; 
                    var filebyte = base64ToBufferArray(fileCont); 
                    downloadFile(fileName, [filebyte]); 
            } else { 
                Xrm.Utility.alertDialog(this.responseText); 
            } 
        } 
    }; 
    req.send(account); 
} 
 
function base64ToBufferArray(base64content) { 
    var binaryString = window.atob(base64content); 
    var binaryLen = binaryString.length; 
    var bytes = new Uint8Array(binaryLen); 
    for (var i = 0; i < binaryLen; i++) { 
        var ascii = binaryString.charCodeAt(i); 
        bytes[i] = ascii; 
    } 
    return bytes; 
} 
 
function downloadFile(name,data) { 
        var blob = new Blob(data, { type: "octet/stream" }), 
            url = window.URL.createObjectURL(blob); 
        if (window.navigator && window.navigator.msSaveOrOpenBlob) { 
            window.navigator.msSaveOrOpenBlob(blob, name); 
        } else { 
            const url = window.URL.createObjectURL(blob); 
            const a = document.createElement('a'); 
            document.body.appendChild(a); 
            a.href = url; 
            a.download = name; 
            a.click(); 
            window.URL.revokeObjectURL(url); 
            document.body.removeChild(a); 
        } 
}

That’s it!! when I am clicking on Download button in CRM Account record, it is downloading my Attachment file from Notes which is with title “CustomerInfoDoc”.

Hope this will help…
Enjoy Ms CRM!!!

Follow on Facebook- FB: MSCRM16Tech

Attaching File from SharePoint Location in Email using Power Automate while working on D365 CRM

What is Issue?

When working on D365 CRM, Some processes needs to send notification as well as approval mails to particular users. In these emails some time users want the files to be attached which is uploaded for any particular record in CRM. Developer faces issue to get the file from SharePoint, because of very few columns available in SharePoint which is created by D365 CRM to SharePoint Integration. So the issues are like how to get the file from SharePoint and attach it email?

The Reason-

Using Workflow or custom plugin it will be much time consuming and also complex coding required with this approach. Developer can choose this approach for sending out simple notifications, emails. But when the requirements comes to file attachment from SharePoint or any other cloud location it will be difficult to handle with this approach. Also if the file is in SharePoint location which is configured using Document management in CRM, location will have limited set of columns, so it becomes difficult to query the SharePoint site using API also.

Solution-

For the first issue, which approach to choose in these scenarios-
Microsoft is already recommending users to use Power Automat instead of CRM Workflows. Power Automate is having multiple connectors and actions available which reduces the coding as well as time efforts. So we can choose Power Automate.

Now second Issue, How to get file from SharePoint location which is configured using Document Management in CRM?
As I already mentioned, Power Automate already having hundreds of connectors and actions, we can use the Get File Action in Power Automate. Now again you will be worried about how you can get particular file from this location as Tittle or any other field will not help here. So we can use FileLeafRef column filter for that.

Lets take scenario –

When user have opportunity where he uploads the template for Opportunity Activity logs in Document section. But before closing opportunity user needs the log template approved by his manager. Suppose there is flag when user submits the approval request.

  1. Trigger action for my Power Automate flow will be “Microsoft Dataverse when a row is added, modified or deleted where I will set row filter as AwaitngApprovalflag eq 1
  2. Now we need to initialize the Array which will work as byte array to store the file retrieved from the SharePoint.
  3. Add new SharePoint action “Get File(Properties Only)” and set SharePoint details with Filter Query – FileLeafRef eq “filename.xlsx” (this will be my log file template name)

4. Now add the SharePoint action “Get File Content” and set site address as SharePoint site, File Identifier as identifier from last action i.e. “Get File (Properties Only)”. This will automatically add Apply to Each loop.
5. Append the Array variable with File Content and file name from the above action “Get File Content”.
Example-
{
“FileName”:”fileName.xlsx”,
“ContentByte”:FileContent
}

7. Add action “Send Email With Option” and set participant and email body, and other details. In attachment section set the Array Variable which we initialized and configured with file content.

8. Add condition action and check the response from the manager in Email like he clicked on Approve or Reject button in email. and based on condition perform the next actions on your D365 CRM Record.

9. The Complete Flow looks like-

Hope this will help…
Enjoy Ms CRM!!!

Follow on Facebook- FB: MSCRM16Tech