Blazor JSInterop Save File

HOW TO SAVE A FILE USING JSINTEROP IN BLAZOR

by

After completing this tutorial, you will know how to download and save a file locally to your computer using JavaScript interop in a Blazor application.

The techniques in this lesson could be used to build upon the functionality of the previous tutorial, where you learned how to write to LocalStorage in a Blazor WebAssembly app. In that tutorial, you created a basic text editor where the contents of a note could be saved across browser sessions.

The JavaScript Component

For now, there is no built-in functionality for saving a file in Blazor. It is necessary to write the function in JavaScript, as you would with more traditional web applications, and then invoke the JavaScript function from within your Blazor application’s C# code.

To begin, create a file called SaveFile.js in your project’s wwwroot folder. This file will contain a JavaScript function that you will call from your C# code.

function FileSaveAs(filename, fileContent) {
    var link = document.createElement('a');
    link.download = filename;
    link.href = "data:text/plain;charset=utf-8," + encodeURIComponent(fileContent)
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
}

The function, named FileSaveAs, takes two arguments, a filename and the content that will form the body of the plaintext document. To save other filetypes, make the appropriate adjustments. Load the script in wwwroot/index.html just before the closing body tag </body>.

<script src="SaveFile.js"></script>

Execute JS Using JSInterop

To use a JSInterop in Blazor, you must inject an instance of the IJSRuntime object into the Razor component from which you wish to execute the JavaScript code. For the purpose of this tutorial, you can use the Index.razor page.

@page "/"
@inject IJSRuntime JSRuntime

You will refer to this instance of IJSRuntime by the name JSRuntime. However, before actually using the object, go ahead and lay out the UI of the page.

<h1>Blazor Download File</h1>

<textarea @bind="noteContent" />
<br />
<button @onclick="DownloadFile">Download</button>

This example consists of a simple textarea field, with value bound to a string, noteContent, and a button whose click event will be handled by a method called DownloadFile.

Next, create the noteContent string variable. Also, define a variable named fileName and initialize it with a default filename, such as note.txt. This name will be used when downloading the file.

@code {
    string noteContent;
    string fileName = "note.txt";
}

Now you are ready to use the JavaScript interop by invoking the instance of the JS runtime you injected previously. You must invoke the JSInterop asynchronously, so do not forget to create the DownloadFile method as an async method.

public async void DownloadFile()
{
    await JSRuntime.InvokeAsync<object>(
        "FileSaveAs",
        fileName,
        noteContent
    );
}

This method calls the FileSaveAs function from SaveFile.js. Remember, you loaded this script file in wwwroot/index.html. The values fileName and fileContent correspond to the two arguments expected by the FileSaveAs function. Since this example’s textarea field is bound to noteContent, the current value of textarea will already be stored in noteContent. When the Download button is clicked, your Blazor application will save the contents of the note as notes.txt.

A Complete Example

You are finished! In this tutorial, you learned how to save a file locally from a Blazor application. You wrote a JavaScript function to open the File > Save As… dialog, and then you used Blazor’s JSInterop capability to execute that function from a C# event handler, passing C# variables to the JavaScript function.

Your completed Index.razor may look like the following.

@page "/"
@inject IJSRuntime JSRuntime

<h1>Blazor Download File</h1>

<textarea @bind="noteContent" />
<br />
<button @onclick="DownloadFile">Download</button>

@code {
    string noteContent;
    string fileName = "note.txt";

    public async void DownloadFile()
    {
        await JSRuntime.InvokeAsync<object>(
            "FileSaveAs",
            fileName,
            noteContent
        );
    }
}

You could use this technique to add functionality to the notepad-like text editor you began developing in the previous tutorial. This time, you could trigger a file download by clicking a button, thus allowing you to save the contents of a given note to your hard drive. If you have any questions, do not hesitate to ask in the comments.


Don't stop learning!

There is so much to discover about C#. That's why I am making my favorite tips and tricks available for free. Enter your email address below to become a better .NET developer.


Did you know?

Our beautiful, multi-column C# reference guides contain more than 150 tips and examples to make it even easier to write better code.

Get your cheat sheets