I don't have a really good answer to why your solution is not working, but it is easy to fix it. It seems like you have only access to file content when you are in the event-handling method.
As a workaround, create a "ViewModel" class for your image presentation.
public class FileViewModel
{
/// helpful in combination with @key to make list rendering more efficient
public Guid Id { get; set; }
public String Name { get; set; }
public String ContentType { get; set; }
public Int64 Size { get; set; }
public Byte[] Content { get; set; }
public String ImageDataUrl { get; set; }
public FileViewModel()
{
Id = Guid.NewGuid();
}
}
Changes to OnInputFileChange
Merge your code from Submit with OnInputFileChange. During the event handling, create a ViewModel instance for each file and save the instance's content.
List<FileViewModel> list = new List<FileViewModel>();
private async Task OnInputFileChange(InputFileChangeEventArgs e)
{
var maxAllowedFiles = 3;
var format = "image/png";
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)}";
list.Add(new FileViewModel
{
Content = buffer,
ImageDataUrl = imageDataUrl,
ContentType = imageFile.ContentType,
Name = imageFile.Name,
Size = imageFile.Size,
});
}
}
I added a remove button to showcase a manipulation of the collection after the content is read.
delete images
@if (list.Count > 0)
{
<h4>Images</h4>
<div class="card" style="width:30rem;">
<div class="card-body">
@foreach (var file in list)
{
<img class="rounded m-1" @key="file.Id" src="@file.ImageDataUrl" />
<button type="button" @onclick="() => RemoveImage(file)">Remove</button>
}
</div>
</div>
}
@code {
private void RemoveImage(FileViewModel file)
{
list.Remove(file);
}
}
Using the detour, you now have full access to the data from your ViewModel instance. You can use these data to submit your file to your service then. In the example, I log the file name and length of the byte array as a proof of concept.
async Task Submit()
{
foreach (var item in list)
{
Console.WriteLine($"file {item.Name} | size {item.Content.Length}");
}
}
entire component
@page "/"
<h3>Upload PNG images</h3>
<p>
<InputFile OnChange="@OnInputFileChange" multiple />
</p>
@if (list.Count > 0)
{
<h4>Images</h4>
<div class="card" style="width:30rem;">
<div class="card-body">
@foreach (var file in list)
{
<img class="rounded m-1" @key="file.Id" src="@file.ImageDataUrl" />
<button type="button" @onclick="() => RemoveImage(file)">Remove</button>
}
</div>
</div>
}
@if (list.Count() > 0)
{
<div class="card" style="width:30rem;">
<div class="card-body">
@foreach (var file in list)
{
<div>@file.Name - @file.ContentType - @file.Size</div>
}
</div>
</div>
}
<button @onclick="Submit">Télécharger</button>
@code {
List<FileViewModel> list = new List<FileViewModel>();
private async Task OnInputFileChange(InputFileChangeEventArgs e)
{
var maxAllowedFiles = 3;
var format = "image/png";
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)}";
list.Add(new FileViewModel
{
Content = buffer,
ImageDataUrl = imageDataUrl,
ContentType = imageFile.ContentType,
Name = imageFile.Name,
Size = imageFile.Size,
});
}
}
private void RemoveImage(FileViewModel file)
{
list.Remove(file);
}
async Task Submit()
{
foreach (var item in list)
{
Console.WriteLine($"file {item.Name} | size {item.Content.Length}");
}
}
}