Unable to bind the selected image file in Blazor file upload

RAMAN RAGAVAN 51 Reputation points
2023-02-04T02:38:07.29+00:00

"This question is updated with minimal sample as my old question doesnt give more info"

I am learning blazor and c# fundas with a simple app.This app will allow you tobrowse all kind of files including images.As all kind files we can browse, i need a seperate classfor images only so when ever user select file, first class-BrowserFileWithStatus list will trigger the second class-MediaVariantUI (lists)

class 1-BrowserFileWithStatus - list of this class NOT  use to bind to the UI

class 2-MediaVariantUI- list of this class will use to bind to the UI

I am able to bind the file name but How i can bind the images in mud card.I dont want to disturb my first class i need to asign my images to second class list.How can I do that? below is my classes and pages.

basicaly i dont want to disturb First class 



//FIRST CLASS

public class BrowserFileWithStatus: FileWithStatusBase

    {

        public BrowserFileWithStatus(IBrowserFile file)

        {

            File = file ?? throw new ArgumentNullException(nameof(file));

            FileName = Path.GetFileName(File.Name);

        }

        public IBrowserFile File { get; }

    }

 public class FileWithStatusBase: IFileWithStatus

    {

        private readonly string fileName = null!;

        public string FileNameWithoutExtension { get; private init; } = null!;

        public string FileExtension { get; private init; } = null!;

        public string FileName

        {

            get => fileName;

            protected init

            {

                fileName = value;

                FileExtension = Path.GetExtension(fileName.AsSpan())[1..].ToString();

                FileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);

            }

        }

    }

 public interface IFileWithStatus

    {

        string FileNameWithoutExtension { get; }

        string FileExtension { get; }

        string FileName { get; }

    }

//SECOND CLASS-USING FOR IMAGE ONLY OPERATIONS

 public class MediaVariantUI

    {

        private BrowserFileWithStatus file;

        public MediaVariantUI(BrowserFileWithStatus file)

        {

            File = file;

            this.file = file;

            Name = file.FileName;

            ContentType = file.File.ContentType;

            FileNameWithoutExtension = file.FileNameWithoutExtension;

        }

        public BrowserFileWithStatus File { get; }

        public String Name { get; set; }

        public String FileNameWithoutExtension { get; set; }

        public String ContentType { get; set; }

    }

//MAIN UI PAGE

@page "/MediaUpload"

@using FileUpload.Models;

<EditForm Model="mediaformmodels" OnValidSubmit="CreateMediaNewFormAsync">

    <FileuploadComponent @bind-SelectedFiles="mediaformmodels.ListFileToUpload"></FileuploadComponent>

    @if (mediaformmodels.ListMediaVariantUI != null && mediaformmodels.ListMediaVariantUI.Count > 0)

            {

        <MudcardComponent MediaVariantUIList="mediaformmodels.ListMediaVariantUI"></MudcardComponent>

            }

    <MudGrid Class="mt-4 pt-1" Justify="Justify.FlexEnd">

        <MudItem>

            <MudButton Size="Size.Large"

                       Variant="Variant.Filled"

                       Color="Color.Primary"

                       StartIcon="@Icons.Material.Outlined.Save"

                       ButtonType="ButtonType.Submit">

                SUBMIT

            </MudButton>

        </MudItem>

    </MudGrid>

</EditForm>

@code {

    private MediaFormModels mediaformmodels = new();

    private async Task CreateMediaNewFormAsync()

    {

        foreach (var mediaFile in mediaformmodels.ListMediaVariantUI.Where(x => x != null))

        {

            //save each media files

        }

    }

}

//MediaFormModels class for mediaformmodels

using System.ComponentModel.DataAnnotations;

namespace FileUpload.Models

{

    public class MediaFormModels

    {

        private List<MediaVariantUI>? listMediaVariantUIValue = new();

        private List<BrowserFileWithStatus>? listFileToUpload = new();

        public IReadOnlyList<BrowserFileWithStatus>? ListFileToUpload

        {

            get

            {

                return listFileToUpload;

            }

            set

            {

                listFileToUpload = value.ToList();

                ListMediaVariantUI = value.Select(file => new MediaVariantUI(file)).ToList();

            }

        }

        public IReadOnlyList<MediaVariantUI>? ListMediaVariantUI

        {

            get { return listMediaVariantUIValue; }

            set { listMediaVariantUIValue = value.ToList(); }

        }

    }

}

//FILE UPLOAD PAGE

@using FileUpload.Models;

<h3>FileuploadComponent</h3>

<InputFile id="fileInput" OnChange="OnFilesChanged" hidden multiple />

<MudButton HtmlTag="label"

           Variant="Variant.Filled"

           Color="Color.Success"

           StartIcon="@Icons.Filled.CloudUpload"

           for="fileInput">

    Upload Image

</MudButton>

@code {

    [Parameter]

    public IReadOnlyList<BrowserFileWithStatus> SelectedFiles { get; set; } = Array.Empty<BrowserFileWithStatus>();

    [Parameter]

    public EventCallback<IReadOnlyList<BrowserFileWithStatus>> SelectedFilesChanged { get; set; }

    private async Task OnFilesChanged(InputFileChangeEventArgs eventArgs)

    {

        //i know following code is used to get image data but how can i asign to second class list when first class list triggered

        //foreach (var imageFile in e.GetMultipleFiles(maxAllowedFiles))

        //{

        //    var resizedImageFile = await imageFile.RequestImageFileAsync(format, 100, 100);

        //    var buffer = new byte[resizedImageFile.Size];

        //    await resizedImageFile.OpenReadStream().ReadAsync(buffer);

        //    var imageDataUrl = $"data:{format};base64,{Convert.ToBase64String(buffer)}";

        //}

        _ = eventArgs ?? throw new ArgumentNullException(nameof(eventArgs));

        var files = new List<BrowserFileWithStatus>(eventArgs.FileCount);

        files.AddRange(eventArgs.GetMultipleFiles(10000).Select(file => new BrowserFileWithStatus(file)));

        SelectedFiles = files;

      await SelectedFilesChanged.InvokeAsync(SelectedFiles).ConfigureAwait(false);

    }

}

For image binding i have a card component

@using FileUpload.Models;

<h3>Display selected Images</h3>

<MudPaper Width="100%" Class="darkbackground" MinHeight="350">

    <MudContainer>

        <MudGrid Spacing="@spacing" Justify="Justify.Center">

            @foreach (var item in MediaVariantUIList)

            {

                <MudItem xs="4" Style="display:flex;">

                    <MudCard Height="350px" Width="300px">

                        <MudCardMedia Image="" Height="200" />

                        <MudCardContent>

                            <input @bind="@item.FileNameWithoutExtension" @bind:event="oninput" />

                            @* <MudTextField @bind-Value="@item.FileNameWithoutExtension" @bind:event="oninput" Label="Name" Variant="Variant.Text" Margin="Margin.Dense"></MudTextField>*@

                            <MudText Class="textsilver" Typo="Typo.body2">@item.Name</MudText>

                        </MudCardContent>

                        <MudCardActions>

                            <MudIconButton Icon="@Icons.Material.Filled.Delete"  Variant="Variant.Outlined" Color="Color.Error" Size="Size.Small" />

                        </MudCardActions>

                    </MudCard>

                </MudItem>

            }

        </MudGrid>

    </MudContainer>

</MudPaper>

@code {

    public int spacing { get; set; } = 2;

    [Parameter]

    public IReadOnlyList<MediaVariantUI> MediaVariantUIList { get; set; } = Array.Empty<MediaVariantUI>();

}
Developer technologies ASP.NET ASP.NET Core
Developer technologies .NET Blazor
Developer technologies C#
{count} votes

2 answers

Sort by: Most helpful
  1. Anonymous
    2023-02-09T10:19:23.6033333+00:00

    Hi @RAMAN RAGAVAN

    I want to preview the image in the mud card.How can i get image url in to UI list

    Try to modify your code as below:

    Add an ImageUri property in the MediaVariantUI class, IFileWithStatus interface, and FileWithStatusBase class.

        public class BrowserFileWithStatus : FileWithStatusBase 
        { 
            public BrowserFileWithStatus(IBrowserFile file) 
            { 
                File = file ?? throw new ArgumentNullException(nameof(file)); 
                FileName = Path.GetFileName(File.Name); 
            } 
            public IBrowserFile File { get; } 
        }
        public class FileWithStatusBase : IFileWithStatus
        {
            private readonly string fileName = null!;
            public string FileNameWithoutExtension { get; private init; } = null!;
            public string FileExtension { get; private init; } = null!;
            public string ImageUri { get; set; }
            public string FileName
            {
                get => fileName;
                protected init
                {
                    fileName = value;
                    FileExtension = Path.GetExtension(fileName.AsSpan())[1..].ToString();
                    FileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
                }
            }
        }
    
        public interface IFileWithStatus
        {
            string FileNameWithoutExtension { get; }
            string FileExtension { get; }
            string FileName { get; }
            string ImageUri { get; set; }
        }
    
        //SECOND CLASS-USING FOR IMAGE ONLY OPERATIONS
        public class MediaVariantUI
        {
            private BrowserFileWithStatus file;
            public MediaVariantUI(BrowserFileWithStatus file)
            {
                File = file;
                this.file = file;
                Name = file.FileName;
                ContentType = file.File.ContentType;
                FileNameWithoutExtension = file.FileNameWithoutExtension;
                ImageUri = file.ImageUri;
            } 
            public BrowserFileWithStatus File { get; }
            public String Name { get; set; }
            public String FileNameWithoutExtension { get; set; }
            public String ContentType { get; set; }
            public string ImageUri { get; set; }
        }
    

    Then, in the FileuploadComponent component: after selecting the file, read the image file and get the based64 string to display the image.

        private async Task OnFilesChanged(InputFileChangeEventArgs eventArgs) 
        { 
            //i know following code is used to get image data but how can i asign to second class list when first class list triggered 
            //foreach (var imageFile in e.GetMultipleFiles(maxAllowedFiles)) 
            //{ 
            //    var resizedImageFile = await imageFile.RequestImageFileAsync(format, 100, 100); 
            //    var buffer = new byte[resizedImageFile.Size]; 
            //    await resizedImageFile.OpenReadStream().ReadAsync(buffer); 
            //    var imageDataUrl = $"data:{format};base64,{Convert.ToBase64String(buffer)}"; 
            //}
    
            _ = eventArgs ?? throw new ArgumentNullException(nameof(eventArgs)); 
            var files = new List<BrowserFileWithStatus>(eventArgs.FileCount); 
             
            files.AddRange(eventArgs.GetMultipleFiles(10000).Select(file => new BrowserFileWithStatus(file)).ToList()); 
    
            foreach (var imagefile in files)
            { 
                var image = await imagefile.File.RequestImageFileAsync("image/jpg", 100, 100);
                using (Stream imageStream = image.OpenReadStream(1024 * 1024 * 10))
                {
                    using MemoryStream ms = new();
                    await imageStream.CopyToAsync(ms);
                    imagefile.ImageUri = $"data:image/png;base64,{Convert.ToBase64String(ms.ToArray())}";
                }
            } 
            SelectedFiles = files; 
            await SelectedFilesChanged.InvokeAsync(SelectedFiles).ConfigureAwait(false);
    
        }
    

    After that, in the MudcardComponent component, use the following code to display image:

    <MudPaper Width="100%" Class="darkbackground" MinHeight="350"> 
        <MudContainer> 
            <MudGrid Spacing="@spacing" Justify="Justify.Center"> 
                @foreach (var item in MediaVariantUIList) 
                { 
                    <MudItem xs="4" Style="display:flex;"> 
                        <MudCard Height="350px" Width="300px">
                            <MudCardMedia Image="@item.ImageUri" Height="200" />
                            <MudCardContent>  
                                <input @bind="@item.FileNameWithoutExtension" @bind:event="oninput" /> 
                                @* <MudTextField @bind-Value="@item.FileNameWithoutExtension" @bind:event="oninput" Label="Name" Variant="Variant.Text" Margin="Margin.Dense"></MudTextField>*@
                                 <MudText Class="textsilver" Typo="Typo.body2">@item.Name</MudText>
                            
                            </MudCardContent>
                            <MudCardActions> 
                                <MudIconButton Icon="@Icons.Material.Filled.Delete" Variant="Variant.Outlined" Color="Color.Error" Size="Size.Small" /> 
                            </MudCardActions> 
                        </MudCard> 
                    </MudItem> 
                } 
            </MudGrid> 
        </MudContainer>
    
    </MudPaper>
    

    The result as below:

    User's image

    i know following code is used to get image data but how can i asign to second class list when first class list triggered

    I know you want directly to display the image via the MediaVariantUI.BrowserFileWithStatus.File, I also checked it, but it not works. So, I suggest you could use the above method.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,

    Dillion

    0 comments No comments

  2. Deleted

    This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.


    Comments have been turned off. Learn more

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.