<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ievafil</title>
    <description>The latest articles on DEV Community by ievafil (@ievafil).</description>
    <link>https://dev.to/ievafil</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3159787%2Fcde644dc-10a2-4665-8c09-5430792251d7.png</url>
      <title>DEV Community: ievafil</title>
      <link>https://dev.to/ievafil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ievafil"/>
    <language>en</language>
    <item>
      <title>Building a Canvas App PCF Control to Download Files from SharePoint</title>
      <dc:creator>ievafil</dc:creator>
      <pubDate>Mon, 26 May 2025 20:40:19 +0000</pubDate>
      <link>https://dev.to/ievafil/building-a-canvas-app-pcf-control-to-download-files-from-sharepoint-3697</link>
      <guid>https://dev.to/ievafil/building-a-canvas-app-pcf-control-to-download-files-from-sharepoint-3697</guid>
      <description>&lt;p&gt;This post will cover how to enable file downloads from SharePoint within a Power Apps (Canvas App) via a PCF component - without granting users direct access to the underlying SharePoint location. The goal is to allow users to trigger the download of a specific file (generated by an external process) to their local machine via a single button click.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivisyyzlrfb4v6v4zgdb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivisyyzlrfb4v6v4zgdb.gif" alt="PCF component enabling file download" width="480" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Visual Studio Code&lt;/li&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;Microsoft Power Platform CLI&lt;/li&gt;
&lt;li&gt;.NET&lt;/li&gt;
&lt;li&gt;PCF components enabled for Canvas Apps in your environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Solution Overview
&lt;/h2&gt;

&lt;p&gt;This solution includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;PCF control&lt;/strong&gt; for handling the file download&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;Power Automate flow&lt;/strong&gt; to retrieve and convert SharePoint files to Base64&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;Canvas App&lt;/strong&gt; that ties everything together&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post will show how to download files stored in SharePoint:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff0ygufwzspmf3cacclg5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff0ygufwzspmf3cacclg5.png" alt="Files stored in SharePoint location" width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;…directly from this Canvas App:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd8heo4bjdm9kuy6hdot9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd8heo4bjdm9kuy6hdot9.png" alt="PCF component enabling file download" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1 PCF Component: File Downloader
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;You can download the PCF solution here:   &lt;a href="https://github.com/ievafil/SPFileDownloader/blob/51a41eddc5f59589bdf97edf41ba5d14c98ebd72/Solutions.zip" rel="noopener noreferrer"&gt;Solutions.zip on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The PCF control handles the actual file download within the Canvas App. It takes file metadata and content as input and triggers a download on the user's device without exposing the SharePoint source.&lt;/p&gt;

&lt;p&gt;There are two main files that define the component, the manifest (&lt;em&gt;ControlManifest.Input.xml&lt;/em&gt;) and the implementation logic (&lt;em&gt;index.ts&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;The manifest file &lt;em&gt;ControlManifest.Input.xml&lt;/em&gt; defines four properties passed in from Power Apps: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;fileName&lt;/code&gt; - The name users will see when the file is downloaded.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fileMIMEType&lt;/code&gt; - The MIME type used to correctly format the file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fileBase64&lt;/code&gt; - The file’s content encoded in Base64.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fileDownload&lt;/code&gt; - A boolean flag that triggers the download.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6wtsbtsk2rvzx2jo307.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6wtsbtsk2rvzx2jo307.png" alt="ControlManifest.Input.xml" width="800" height="71"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;index.ts&lt;/em&gt; file contains the component logic:&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;UpdateView()&lt;/em&gt; method listens for changes in the control's context and initiates a file download if the &lt;em&gt;fileDownload&lt;/em&gt; flag is set to true. It creates a temporary &lt;em&gt;a&lt;/em&gt; element with the file data, triggers the download, and then signals the framework to reset the flag to avoid repeated downloads.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4rpb8jyfj300aajwslh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4rpb8jyfj300aajwslh.png" alt="UpdateView method" width="602" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;getOutputs()&lt;/em&gt; method resets &lt;em&gt;fileDownload&lt;/em&gt; to false to ensure the download only occurs once per trigger.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rjaovtste9yglr81id4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rjaovtste9yglr81id4.png" alt="getOutputs method" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2 Power Automate Flow: Convert SharePoint File to Base64
&lt;/h2&gt;

&lt;p&gt;A Power Automate Flow that takes the name of a file in a SharePoint location (passed through from a Canvas App) and returns the file MIMEType and the file as base64.&lt;/p&gt;

&lt;p&gt;The MIMEtype of the file is obtained via &lt;code&gt;body('Get_file_content_using_path')?['$content-type']&lt;/code&gt;&lt;br&gt;
The file as base64 is obtained via &lt;code&gt;outputs('Get_file_content_using_path')?['body']?['$content']&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkeeswynbc8endv73i4et.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkeeswynbc8endv73i4et.png" alt="Power Automate Flow" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3 Canvas App: Integration
&lt;/h2&gt;

&lt;p&gt;Steps to connect it all up in your Canvas App:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Import the PCF component&lt;/strong&gt; into your environment as a solution:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In Power Apps, go to &lt;strong&gt;Insert &amp;gt; Code components,&lt;/strong&gt; and add the control to your screen:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftgxqcb1shudaqa64irjo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftgxqcb1shudaqa64irjo.png" alt="Inserting PCF Component" width="800" height="182"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add your Power Automate flow&lt;/strong&gt; to the app:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr468qpcwawykmv13i7yb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr468qpcwawykmv13i7yb.png" alt="Add flow in canvas app" width="422" height="386"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add UI Elements:&lt;/strong&gt;&lt;br&gt;
-A text input field (e.g., TextInput1) for the filename&lt;br&gt;
-A Download button&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set the OnSelect property&lt;/strong&gt; of the Download button to the following:&lt;br&gt;
&lt;code&gt;Set(fileDownload, false);&lt;br&gt;
Set(flowResult, Filetobase64.Run(TextInput1.Text));&lt;br&gt;
Set(fileBase64, flowResult.base64);&lt;br&gt;
Set(fileType, flowResult.filetype);&lt;br&gt;
Set(fileDownload, true);&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bind the PCF component properties&lt;/strong&gt; to the variables you’ve set:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvu9jtmoj9897uqbinqap.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvu9jtmoj9897uqbinqap.png" alt="Set parameters" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test it out&lt;/strong&gt; by providing a filename and clicking the Download button&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frw924r7fhxjzxuh46n9n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frw924r7fhxjzxuh46n9n.png" alt="Set the Parameters" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This approach provides a secure and user-friendly way to enable file downloads from SharePoint without giving users direct access to the document library. It’s lightweight, flexible, and can be extended to support dynamic files or other data sources.&lt;/p&gt;

</description>
      <category>pcf</category>
      <category>powerapps</category>
      <category>sharepoint</category>
      <category>powerplatform</category>
    </item>
  </channel>
</rss>
