Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I upload files with Blazor?

I found the BlazorInputFile library, but there are still-open PRs from October of 2019, and I am not sure whether this library is still maintained. Also, I found a couple articles in blogs about how we can upload files with JS in Blazor. While I don't want to use JS if possible, I do need to upload files using Blazor... is it possible to do so without using JavaScript?

like image 613
Sergey Pitenko Avatar asked Apr 01 '20 16:04

Sergey Pitenko


People also ask

Can Blazor access file system?

The Blazor File Manager is a graphical user interface component for managing the file system that allows users to perform most common file operations like accessing, editing, and sorting files or folders. This component also provides easy navigation for browsing folders to select a file or folder from the file system.

Does Blazor need a web server?

Static site hosting Blazor WebAssembly apps don't require a server to execute server-side code in order to download and run. Blazor WebAssembly apps can be delivered via a Content Delivery Network (CDN) (for example, Azure CDN). If static hosting is an app requirement, select Blazor WebAssembly.

How do I publish my Blazor hosted app?

Publish the app Publish a hosted Blazor WebAssembly solution from the Server project. Select the Publish {APPLICATION} command from the Build menu, where the {APPLICATION} placeholder the app's name. Select the publish target. To publish locally, select Folder.

How do I upload an image using fileupload in Blazor?

We begin by creating a FileUpload component in the Pages folder: Here, we are using the @page attribute, to let Blazor know that we want this component to be routable. Next, we want to add the input element that allows us to select a file to upload, as well as an <img> HTML element that will display our uploaded image:

What is inputfile for Blazor server and Blazor WebAssembly?

One of the additions for Blazor Server and Blazor WebAssembly is the InputFile component to deal with file uploads. In this article I am going to take a quick look at the InputFile component and discuss a possible file upload process for Blazor Server as well as Blazor WebAssembly (ASP.NET Core hosted) apps.

What is the difference between Blazor WebAssembly and Blazor server?

In Blazor WebAssembly, file data is streamed directly into the .NET code within the browser. In Blazor Server, file data is streamed over the SignalR connection into .NET code on the server as the file is read. Always follow security best practices when permitting users to upload files.

How do I import file data into Blazor?

The file data needs to get into Blazor via the existing JS interop mechanism. Provides access to the file data as a regular .NET Stream, so other code can handle it just the same as if it were a normal file on disk. This must literally stream the content into the .NET process, since we don’t want to depend on loading it all into memory at once.


Video Answer


3 Answers

I was dabbling with installing SteveSandersonMS' repo and then realised that, as of February 2021, there is actually a native InputFile component in ASP.NET Core 5.0.

It supports uploading of single and multiple files in Blazor and is easy to use (and you don't need to add your own JS files etc.).

I used it for single file uploads - all you need to do is add the InputFile component in the Razor page:

<InputFile OnChange="@SingleUpload" />

and then in my case I needed the file in a byte array:

@code {

   private async Task SingleUpload(InputFileChangeEventArgs e)
   {
       MemoryStream ms = new MemoryStream();
       await e.File.OpenReadStream().CopyToAsync(ms);
       var bytes = ms.ToArray();
       //do something with bytes
   }
}

InputFileChangeEventArgs gives you an IReadOnlyList of IBrowserFile which you can use to get the Name, LastModified, Size and ContentType, as well as an OpenReadStream method for getting a Stream.

There is good documentation and code on how to get multiple files in the ASP.NET docs.

Your will also need to add the System.IO namespace:

@using System.IO
like image 140
AlbertGromek Avatar answered Oct 20 '22 19:10

AlbertGromek


As of June 2020, The best method (WA), assuming you are using a form is to use a Tewr's FileReader. Let start with the API, the post controller would be :

      public async Task<IActionResult> PostMedia(
        [FromForm] IFormFile Picture,
        [FromForm] string Focus,
        [FromForm] string ID,
        [FromForm] string Title,
        [FromForm] string FormType,
        [FromForm] string AnimalType,
        [FromForm] string Mode,
        [FromForm] string AnimalID
        )
    {
        Debug.WriteLine($"-------------------------------------{Focus}-----------------------------------------------");
        Debug.WriteLine($"-------------------------------------{ID}-----------------------------------------------");
        Debug.WriteLine($"-------------------------------------{Title}-----------------------------------------------");
        Debug.WriteLine($"-------------------------------------{FormType}-----------------------------------------------");
        Debug.WriteLine($"-------------------------------------{AnimalType}-----------------------------------------------");
        Debug.WriteLine($"-------------------------------------{Mode}-----------------------------------------------");
        Debug.WriteLine($"-------------------------------------{AnimalID}-----------------------------------------------");


        //check if file was fully uploaded
        if (Picture.Length == 0 || Picture == null)

            return BadRequest("Upload a new File");
        else
            return Ok ("do something with this data....") 
     }

Then the post method on the client side would be:

    public async Task PostFile()
  {
    //create content headers
    var content = new MultipartFormDataContent();
    content.Headers.ContentDisposition = new 
    System.Net.Http.Headers.ContentDispositionHeaderValue("form-data");

    //create content
    content.Add(new StreamContent(Pic.Stream, (int)Pic.Stream.Length), "Picture", Pic.FileName);
    content.Add(new StringContent(Pic.Title), "Title");
    content.Add(new StringContent(Pic.Focus), "Focus");
    content.Add(new StringContent(Pic.ID), "ID");
    content.Add(new StringContent(Pic.FormType), "FormType");
    content.Add(new StringContent(Pic.AnimalType), "AnimalType");
    content.Add(new StringContent(Pic.Mode), "Mode");
    content.Add(new StringContent(Pic.AnimalID), "AnimalID");
    //call to the server
    var upload = await Http.PostAsync("Media",content);

    //get server response
    Pic.Message = await upload.Content.ReadAsStringAsync();
   }

Tewr File reader helps you read the file into a stream which in my case is passed to the Pic object. The reading function which is binded to the onchange of your input element in the form would be :

  public async Task ReadFile()
   {
    var file = (await fileReaderService.CreateReference(Xelement).EnumerateFilesAsync()).FirstOrDefault();

    if (file == null)  return;


    var fileInfo = await file.ReadFileInfoAsync();

    Pic.FileName = fileInfo.Name;


    // Read into RAM
    using (var memoryStream = await file.CreateMemoryStreamAsync((int)fileInfo.Size))
    {
        // Copy store image into pic object
        Pic.Stream = new MemoryStream(memoryStream.ToArray());
    }

}

Note that Xelement is ElementReference, and it used as ref on the input element in the form.

like image 3
Xserge Avatar answered Oct 20 '22 18:10

Xserge


At the current state of affairs (as 2 April 2020), you will require JS, it is inevitable.

There are two main approaches you can take:

  • get the file data in the onchange event of the input, and call C# methods by passing the byte[] to them - that's basically the file selector approach you linked where you get the file data in the Blazor app to do whatever you want with it.

  • get the file data in the onchange event of the input, and use JS to call a remote endpoint that will receive the file and do something with it (like save it on your NAS or put it in your DB). This one is an actual file upload, as opposed to a file selector.

Both approaches are similar from coding perspective - you need JS. Perhaps in a future version of Blazor we will get an <InputFile> that will do the selection so you can to uploads with C# HTTP requests.

The File Selector approach is relatively easy to implement (literally a few lines), but it does not give you a file on the server, you have to work for it a little. The File Upload approach is harder to get right. I would personally use someone else's package for either. For file uploads things like Telerik UI for Blazor can be a commercial fit, and for the simpler selectors there is already another answer that links examples. By the way, Telerik's demos also have one such example as a component implemented for some of the demos.

like image 1
rdmptn Avatar answered Oct 20 '22 17:10

rdmptn