9

Is there a way to download a file, generated dynamically in memory in Blazor Server Side without need to store it on a filesystem?

Yurii Zhukow
  • 345
  • 1
  • 2
  • 10
  • 1
    I don't think there is anthing built into Blazor but you can add an MVC Controller and generate the file there. So construct an URL with the parameters to do that. But consider if that could be exploited. – H H Jan 05 '20 at 22:29
  • Henk, yes, the good approach will be to add MVC controller into Blazor server side app. Unfortunately, the most suggestions, googled in the web are about adding Blazor into existing MVC - not vice versa. – Yurii Zhukow Jan 06 '20 at 03:26

2 Answers2

8

The solution was in adding Web Api contoller into Blazor server side app.

  1. Add Controllers/DownloadController.cs controller to the root of Blazor app:
[ApiController, Route("api/[controller]")]
    public class DownloadController : ControllerBase {

        [HttpGet, Route("{name}")]
        public ActionResult Get(string name) {

            var buffer = Encoding.UTF8.GetBytes("Hello! Content is here.");
            var stream = new MemoryStream(buffer);
            //var stream = new FileStream(filename);

            var result = new FileStreamResult(stream, "text/plain");
            result.FileDownloadName = "test.txt";
            return result;
        }


    }
  1. Adjust Startup.cs of the Blazor app to support controllers routing:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {

            ...

            app.UseRouting();

            app.UseEndpoints(endpoints => {

                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller}/{action}");

                endpoints.MapControllers();

                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");

            });

        }
Yurii Zhukow
  • 345
  • 1
  • 2
  • 10
  • Thanks, works well and can't get simpler. However, an annoying thig is that the download web api url will show up on the adress bar, obviously, while this can be avoided when using a javascript based download routine or just when downloading a file with plain a/href with download attribute (as seen on https://www.w3schools.com/tags/att_a_download.asp). Not sure how to get around this without JS interop. – Ale Feb 17 '20 at 07:05
  • 3
    The above issue very easily avoided using JS-interop as described here; https://www.syncfusion.com/kb/10358/how-to-create-a-pdf-file-in-blazor-using-c – Ale Feb 17 '20 at 09:18
  • Blazor server side is not suposed to have a Controller – MarchalPT Jul 16 '21 at 16:31
  • @MarchalPT - Why is it not supposed to? Do you have a link for that? [citation needed] – H H Jul 21 '21 at 18:14
  • @HenkHolterman For start, you can download without an api, using a cshtml page and of course you can add an API for specific endpoints but the whole point of Blazor server is to run all code in server. – MarchalPT Jul 21 '21 at 19:29
3

Create a cshtml page in Blazor like bellow.

FileDownload.cshtml.cs:

public class FileDownloadsModel : PageModel
{        
    public async Task<IActionResult> OnGet()
    {
        byte[] fileContent = ....;                                  

        return File(fileContent, "application/force-download", "test.txt");
    }       
}

FileDownload.cshtml:

@page "/download/{object}/{id:int}/{fileType}" 
@model GFProdMan.Pages.FileDownloadsModel

And that is simply it.

MarchalPT
  • 1,268
  • 9
  • 28