From f894e2b3bab9eca24286d14833c761fcbb5e67a1 Mon Sep 17 00:00:00 2001
From: Duncan <96219296+DuncanDPS@users.noreply.github.com>
Date: Fri, 14 Aug 2026 15:28:54 -0600
Subject: [PATCH 1/2] Support multiple file uploads with progress bar
Improved SubirArchivo.razor to allow multiple file selection and display upload progress. Updated SubirArchivoMetodo for multi-file handling, progress updates, and better error/UI state management. Refactored ArchivoService and IArchivoService to support progress callbacks, enabling real-time progress updates during chunked uploads.
---
FrontApp/Pages/SubirArchivo.razor | 67 ++++++++++++++++++++-------
FrontApp/Servicios/ArchivoService.cs | 15 ++++--
FrontApp/Servicios/IArchivoService.cs | 2 +-
3 files changed, 63 insertions(+), 21 deletions(-)
diff --git a/FrontApp/Pages/SubirArchivo.razor b/FrontApp/Pages/SubirArchivo.razor
index 67fdcff..41e72fc 100644
--- a/FrontApp/Pages/SubirArchivo.razor
+++ b/FrontApp/Pages/SubirArchivo.razor
@@ -7,41 +7,74 @@
Subir Archivo - NubeCasera
-
-
Subir Archivo
-
-@*
-
Seleccionar Archivo:
-
-
*@
-
+
+
-
+
+@if (subiendoArchivo)
+{
+
+}
@code {
[Parameter]
public Guid? CategoriaId { get; set; }
- // este codigo, recibe 1 IFormFile por request, se enfoca en el loop
- // se puede optimizar modificando o creando un endpoint recibiendo
- // List.
+ // Variables para la barra de progreso
+ private int progresoActual = 0;
+ private bool subiendoArchivo = false;
+
public async Task SubirArchivoMetodo(InputFileChangeEventArgs e)
{
var archivos = e.GetMultipleFiles();
const long MaxFileSize = 5L * 1024L * 1024L * 1024L;
- foreach (var archivo in archivos)
+ // Mostrar la barra de progreso
+ subiendoArchivo = true;
+ progresoActual = 0;
+
+ try
{
- await using var stream = archivo.OpenReadStream(maxAllowedSize: MaxFileSize);
- // IBrowserFile file, Guid IdCategoria, long maxAllowedSize
- await ArchivoService.SubirArchivoAsync(archivo, CategoriaId ?? Guid.Empty, MaxFileSize);
+ foreach (var archivo in archivos)
+ {
+ await ArchivoService.SubirArchivoAsync(
+ archivo,
+ CategoriaId ?? Guid.Empty,
+ MaxFileSize,
+ (porcentaje) =>
+ {
+ progresoActual = porcentaje;
+ StateHasChanged(); // Actualizar la UI
+ }
+ );
+ }
}
+ catch (Exception ex)
+ {
+ // Manejar errores (por ejemplo, mostrar un mensaje)
+ Console.WriteLine($"Error: {ex.Message}");
+ }
+ finally
+ {
+ // Ocultar la barra al terminar (éxito o error)
+ subiendoArchivo = false;
+ progresoActual = 0;
+ }
+
Navigation.NavigateTo("/archivos");
-
}
}
\ No newline at end of file
diff --git a/FrontApp/Servicios/ArchivoService.cs b/FrontApp/Servicios/ArchivoService.cs
index bde4554..771cba2 100644
--- a/FrontApp/Servicios/ArchivoService.cs
+++ b/FrontApp/Servicios/ArchivoService.cs
@@ -10,11 +10,16 @@ namespace Front.Servicios
public class ArchivoService : IArchivoService
{
private readonly HttpClient _httpClient;
+
+ //public Action? OnProgresoActualizado;
+
public ArchivoService(HttpClient httpClient)
{
_httpClient = httpClient;
}
+
+
public async Task> ObtenerArchivosAsync(Guid? categoriaId = null)
{
var url = categoriaId.HasValue
@@ -38,8 +43,8 @@ public async Task EliminarArchivoAsync(Guid id)
response.EnsureSuccessStatusCode();
}
- #region working on!
- public async Task SubirArchivoAsync(IBrowserFile file, Guid IdCategoria, long maxAllowedSize)
+
+ public async Task SubirArchivoAsync(IBrowserFile file, Guid IdCategoria, long maxAllowedSize, Action OnProgresoActualizado)
{
const int chunkSize = 4 * 1024 * 1024; // 4 MB por chunk
var IdSubida = Guid.NewGuid().ToString();
@@ -78,6 +83,10 @@ public async Task SubirArchivoAsync(IBrowserFile file, Guid IdCategoria, long ma
// importante: pedir que el browser use streaming si esta disponible
req.SetBrowserRequestStreamingEnabled(true);
+ // porcentaje de carga de chunks, para actualizar la barra de progreso
+ int porcentaje = (int)((chunkIndex + 1) * 100.0 / chunksTotales);
+ OnProgresoActualizado?.Invoke(porcentaje);
+
using var resp = await _httpClient.SendAsync(req, HttpCompletionOption.ResponseHeadersRead);
resp.EnsureSuccessStatusCode();
chunkIndex++;
@@ -85,7 +94,7 @@ public async Task SubirArchivoAsync(IBrowserFile file, Guid IdCategoria, long ma
}
- #endregion
+
public string ObtenerUrlDescarga(Guid id)
{
diff --git a/FrontApp/Servicios/IArchivoService.cs b/FrontApp/Servicios/IArchivoService.cs
index d0edba0..97d7713 100644
--- a/FrontApp/Servicios/IArchivoService.cs
+++ b/FrontApp/Servicios/IArchivoService.cs
@@ -5,7 +5,7 @@ namespace Front.Servicios
{
public interface IArchivoService
{
- Task SubirArchivoAsync(IBrowserFile file, Guid IdCategoria, long maxAllowedSize);
+ Task SubirArchivoAsync(IBrowserFile file, Guid IdCategoria, long maxAllowedSize, Action OnProgresoActualizado);
Task> ObtenerArchivosAsync(Guid? categoriaId = null);
Task ObtenerArchivoAsync(Guid id);
Task> BuscarArchivosAsync(string? q, Guid? categoriaId = null);
From 5ab95bb9001d537c1eb2b7b0a8dda02cc56cecc9 Mon Sep 17 00:00:00 2001
From: Duncan <96219296+DuncanDPS@users.noreply.github.com>
Date: Tue, 18 Aug 2026 14:06:09 -0600
Subject: [PATCH 2/2] Refactor file upload UI and logic for multiple files
Changed input handler to store selected files in archivosSeleccionados. Added UI to list selected files and enable upload button when files are chosen. Refactored SubirArchivos to upload all selected files with progress bar and disabled button during upload. Updated UI to reflect upload state and removed navigation to "/archivos" after upload.
---
FrontApp/Pages/SubirArchivo.razor | 60 ++++++++++++++++++++++++-------
1 file changed, 48 insertions(+), 12 deletions(-)
diff --git a/FrontApp/Pages/SubirArchivo.razor b/FrontApp/Pages/SubirArchivo.razor
index 41e72fc..40f5ad4 100644
--- a/FrontApp/Pages/SubirArchivo.razor
+++ b/FrontApp/Pages/SubirArchivo.razor
@@ -13,21 +13,50 @@
-
+
+
+
+
+@if (archivosSeleccionados != null && archivosSeleccionados.Count > 0)
+{
+
+
Archivos Seleccionados: @archivosSeleccionados.Count
+
+ @foreach (var archivo in archivosSeleccionados)
+ {
+ - @archivo.Name (@(archivo.Size / 1024) KB)
+ }
+
+
+
+
+}
+
@if (subiendoArchivo)
{
- @progresoActual%
+ aria-valuemin="0"
+ aria-valuemax="100">
+ @progresoActual%
-
+
}
@code {
@@ -38,9 +67,18 @@
private int progresoActual = 0;
private bool subiendoArchivo = false;
- public async Task SubirArchivoMetodo(InputFileChangeEventArgs e)
+ // variable para guardar los archivos seleccionados
+ private IReadOnlyList? archivosSeleccionados;
+
+ // obtiene los archivos seleccionados y los guarda en la variable archivosSeleccionados
+ private void ArchivosSeleccionados(InputFileChangeEventArgs e)
{
- var archivos = e.GetMultipleFiles();
+ archivosSeleccionados = e.GetMultipleFiles();
+ }
+
+ public async Task SubirArchivos()
+ {
+ if (archivosSeleccionados == null || archivosSeleccionados.Count == 0)return;
const long MaxFileSize = 5L * 1024L * 1024L * 1024L;
// Mostrar la barra de progreso
@@ -49,7 +87,7 @@
try
{
- foreach (var archivo in archivos)
+ foreach (var archivo in archivosSeleccionados)
{
await ArchivoService.SubirArchivoAsync(
archivo,
@@ -74,7 +112,5 @@
subiendoArchivo = false;
progresoActual = 0;
}
-
- Navigation.NavigateTo("/archivos");
}
}
\ No newline at end of file