Ajax en ASP.NET Core MVC: Enviar archivos al Servidor con jQuery

En este artículo, exploraremos cómo implementar la funcionalidad de envío de archivos al servidor utilizando Ajax en una aplicación ASP.NET Core. Enviar archivos a través de Ajax puede mejorar la experiencia del usuario al permitir que los archivos se carguen de manera asíncrona sin necesidad de recargar la página.

Preparación del Entorno

Antes de comenzar, asegúrate de tener instalado Visual Studio con las herramientas de desarrollo de ASP.NET Core. Este proyecto servirá como base para desarrollar nuestra funcionalidad de envío de archivos al Servidor.

1. Instalación de Visual Studio

  • Descargar Visual Studio: Visita el sitio web de Visual Studio y descarga la versión adecuada para ti (Community, Professional o Enterprise).
  • Seleccionar la carga de trabajo: Durante la instalación, selecciona "Desarrollo de ASP.NET y web" para instalar todas las herramientas necesarias.

 

2. Crear un Nuevo Proyecto ASP.NET Core

  1. Abrir Visual Studio:

    • Selecciona "Crear un nuevo proyecto".
  2. Seleccionar Plantilla de Proyecto:

    • Busca "ASP.NET Core Web Application".
    • Selecciona la plantilla "Aplicación web (Model-View-Controller)" y haz clic en "Siguiente".
  3. Configurar el Proyecto:

    • Nombra tu proyecto, por ejemplo, FileUploadExample.
    • Selecciona una ubicación para guardarlo y haz clic en "Crear".
  4. Seleccionar la Versión de .NET Core:

    • Elige .NET Core 3.1 o superior.
    • Asegúrate de que la plantilla seleccionada sea "Aplicación web (Model-View-Controller)".
    • Haz clic en "Crear".

 

3. Configuración Adicional

  1. Configurar la Carpeta de Subida de Archivos:
    • Dentro de wwwroot, crea una carpeta llamada uploads para almacenar los archivos subidos.

 

4. Incluir jQuery desde un CDN

Nota: Un CDN (Content Delivery Network) es una red de servidores distribuidos geográficamente que trabajan juntos para entregar contenido de Internet de manera rápida y eficiente. Los CDNs se utilizan para distribuir archivos estáticos como imágenes, archivos CSS, archivos JavaScript, y otros recursos de sitios web.

Para usar jQuery, inclúyelo en tu archivo _Layout.cshtml ubicado en Views/Shared:

<!DOCTYPE html>
<html>
<head>
    <!-- Otros enlaces y estilos -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
    <!-- Contenido del cuerpo -->
</body>
</html>

Este script se cargará en todas las páginas de tu aplicación y permitirá el uso de jQuery para realizar solicitudes Ajax.

Nota: <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>. Esta línea de código carga jQuery desde el CDN de Google. Especifica la versión específica de jQuery que deseas utilizar (en este caso, la versión 3.5.1). Este CDN es ampliamente utilizado y es una forma eficiente de incluir jQuery en tu proyecto, asegurando que se cargue rápidamente para los usuarios de todo el mundo.

 

Creación del Modelo y Controlador

En este ejemplo, no necesitamos un modelo específico, pero sí crearemos un controlador FileUploadController con una acción UploadFile que manejará las solicitudes de subida de archivos.

Controlador FileUploadController

Este controlador incluye una acción UploadFile que toma un parámetro file (el archivo que el usuario sube). Si el archivo es válido y tiene contenido, se guarda en la carpeta wwwroot/uploads del servidor y se devuelve una respuesta JSON indicando el éxito de la operación.

using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Threading.Tasks;

public class FileUploadController : Controller
{
    private readonly IWebHostEnvironment _environment;

    // El constructor recibe una instancia de IWebHostEnvironment
    public FileUploadController(IWebHostEnvironment environment)
    {
        _environment = environment;
    }

    // Acción que maneja la subida de archivos
    [HttpPost]
    public async Task<IActionResult> UploadFile(IFormFile file)
    {
        if (file != null && file.Length > 0)
        {
            // Obtener el nombre del archivo
            var fileName = Path.GetFileName(file.FileName);
            
            // Crear la ruta completa para guardar el archivo en wwwroot/uploads
            var filePath = Path.Combine(_environment.WebRootPath, "uploads", fileName);

            // Guardar el archivo en el servidor
            using (var stream = new FileStream(filePath, FileMode.Create))
            {
                await file.CopyToAsync(stream);
            }

            return Json(new { success = true, message = "File uploaded successfully!" });
        }
        return Json(new { success = false, message = "No file uploaded." });
    }
}

Explicación de IWebHostEnvironment

  1. Qué es IWebHostEnvironment:

    • IWebHostEnvironment es una interfaz proporcionada por ASP.NET Core que representa el entorno de alojamiento web de la aplicación.
    • Proporciona propiedades y métodos para obtener información sobre el entorno de alojamiento, como la ruta raíz de la web (WebRootPath), la ruta raíz del contenido (ContentRootPath), y el nombre del entorno (EnvironmentName).
  2. Cómo se instancia IWebHostEnvironment:

    • ASP.NET Core usa la Inyección de Dependencias para gestionar las instancias de IWebHostEnvironment.
    • Cuando ASP.NET Core crea el controlador, automáticamente inyecta una instancia de IWebHostEnvironment en el constructor del controlador.
    • No necesitas instanciar IWebHostEnvironment manualmente; ASP.NET Core lo hace por ti.
  3. Cómo se utiliza IWebHostEnvironment:

    • En el controlador, IWebHostEnvironment se utiliza para acceder a la ruta de la carpeta wwwroot mediante la propiedad WebRootPath.
    • Esto es útil para construir rutas completas a archivos o carpetas dentro de wwwroot.

 

Uso de WebRootPath

La propiedad WebRootPath de IWebHostEnvironment proporciona la ruta física a la carpeta wwwroot en el servidor. Aquí se utiliza para construir la ruta completa donde se guardará el archivo subido.

// Crear la ruta completa para guardar el archivo en wwwroot/uploads
var filePath = Path.Combine(_environment.WebRootPath, "uploads", fileName);
  • Path.Combine: Combina múltiples cadenas en una ruta de archivo válida.
  • _environment.WebRootPath: Proporciona la ruta física a wwwroot.
  • "uploads": La subcarpeta dentro de wwwroot donde se guardará el archivo.
  • fileName: El nombre del archivo subido.

Nota: Al combinar los elementos anteriores, filePath contendrá la ruta completa a donde se guardará el archivo, por ejemplo: C:\path\to\your\project\wwwroot\uploads\filename.ext.

 

Creación de la Vista

En este ejemplo, vamos a crear una vista Index.cshtml que permitirá a los usuarios seleccionar y subir archivos al servidor utilizando Ajax.

  • Abre Visual Studio y navega hasta la carpeta Views del proyecto.
  • Dentro de Views, encuentra la carpeta FileUpload (o créala si no existe).
  • Dentro de FileUpload, crea un nuevo archivo de vista Razor llamado Index.cshtml.

A continuación se muestra el código completo de la vista, seguido de una explicación detallada:

@{
    ViewData["Title"] = "File Upload Example";
}

<h2>File Upload Example</h2>

<form id="uploadForm" enctype="multipart/form-data">
    <div>
        <label for="file">Choose a file to upload:</label>
        <input type="file" id="file" name="file" />
    </div>
    <div>
        <input type="button" id="uploadButton" value="Upload" />
    </div>
</form>

<div id="uploadStatus"></div>

@section Scripts {
    <script type="text/javascript">
        $(document).ready(function () {
            $('#uploadButton').click(function () {
                
                var fileInput = $('#file')[0];
                var files = fileInput.files;
                
                if (files.length > 0) {
                    
                    var formData = new FormData();
                    formData.append('file', files[0]);

                    $.ajax({
                        url: '@Url.Action("UploadFile", "FileUpload")',
                        type: 'POST',
                        data: formData,
                        contentType: false,
                        processData: false,
                        success: function (response) {
                            if (response.success) {
                                $('#uploadStatus').html('<p style="color: green;">' + response.message + '</p>');
                            } else {
                                $('#uploadStatus').html('<p style="color: red;">' + response.message + '</p>');
                            }
                        },
                        error: function () {
                            $('#uploadStatus').html('<p style="color: red;">An error occurred while uploading the file.</p>');
                        }
                    });
                } else {
                    $('#uploadStatus').html('<p style="color: red;">Please select a file to upload.</p>');
                }
            });
        });
    </script>
}

 

Explicación Detallada de la Vista y Ajax

  • Formulario HTML:

    • <form id="uploadForm" enctype="multipart/form-data">: El formulario permite a los usuarios seleccionar un archivo para subir.
    • <input type="file" id="file" name="file" />: Campo de entrada para seleccionar el archivo.
  • Botón de Subida:

    • <input type="button" id="uploadButton" value="Upload" />: Al hacer clic en este botón, se activará la función de subida de archivos mediante Ajax.
  • Div para Mostrar el Estado de la Subida:

    • <div id="uploadStatus"></div>: Este div mostrará mensajes de éxito o error después de intentar subir un archivo.
  • Sección de Scripts:

    • @section Scripts { ... }: En esta sección, se incluyen los scripts JavaScript necesarios para manejar la subida de archivos mediante Ajax.
  • Script de jQuery Ajax:

    • $(document).ready(function () { ... });: Este script se ejecuta cuando el documento está listo.
    • $('#uploadButton').click(function () { ... });: Este evento se activa cuando se hace clic en el botón de subida.
  • Función de Subida de Archivos Ajax:

    • Dentro del evento de clic ($('#uploadButton').click(function () { ... });):
      • Se obtiene el archivo seleccionado (var files = fileInput.files;).
      • Se crea un objeto FormData para almacenar el archivo seleccionado (var formData = new FormData(); formData.append('file', files[0]);).
      • Se realiza una solicitud Ajax utilizando $.ajax():
        • url: Especifica la URL de la acción del controlador que manejará la subida ('@Url.Action("UploadFile", "FileUpload")').
        • type: El método HTTP para la solicitud ('POST' en este caso).
        • data: Los datos que se enviarán al servidor (el objeto FormData que contiene el archivo).
        • contentType: false y processData: false: Configuraciones necesarias para enviar correctamente datos de tipo FormData con Ajax.
        • success: Una función de callback que se ejecuta si la solicitud es exitosa, mostrando un mensaje de éxito o error en #uploadStatus.
        • error: Una función de callback que se ejecuta si hay un error durante la solicitud Ajax, mostrando un mensaje de error en #uploadStatus.

Nota: Un resumen del funcionamiento sería el siguiente...

1. Cuando el usuario hace clic en #uploadButton, se activa la función de subida de archivos.
2. Se prepara un objeto FormData con el archivo seleccionado.
3. Se utiliza $.ajax() para enviar la solicitud al servidor de forma asíncrona.
4. Dependiendo de la respuesta del servidor (success o error), se actualiza dinámicamente el contenido de #uploadStatus para informar al usuario sobre el resultado de la subida.

 

Optimización y buenas prácticas

Validación del Lado del Cliente

La validación del lado del cliente es crucial para proporcionar una experiencia de usuario fluida y prevenir errores antes de enviar los datos al servidor. Aquí se explicará cómo implementar la validación del lado del cliente en la subida de archivos.

Ejemplo de Validación del Lado del Cliente

En la vista Index.cshtml, vamos a agregar validaciones básicas utilizando HTML5 y jQuery para asegurarnos de que el usuario seleccione un archivo antes de intentar la subida.

@{
    ViewData["Title"] = "File Upload Example";
}

<h2>File Upload Example</h2>

<form id="uploadForm" enctype="multipart/form-data">
    <div>
        <label for="file">Choose a file to upload:</label>
        <input type="file" id="file" name="file" accept=".txt,.pdf,.doc,.docx" required />
        <span class="text-danger" id="fileError" style="display:none;">Please select a file to upload.</span>
    </div>
    <div>
        <input type="button" id="uploadButton" value="Upload" />
    </div>
</form>

<div id="uploadStatus"></div>

@section Scripts {
    <script type="text/javascript">
        $(document).ready(function () {
            $('#uploadButton').click(function () {
                
                var fileInput = $('#file')[0];
                var files = fileInput.files;
                
                if (files.length === 0) {
                    $('#fileError').show();
                    return; // Evitar enviar la solicitud si no se selecciona ningún archivo
                } else {
                    $('#fileError').hide();
                }

                var formData = new FormData();
                formData.append('file', files[0]);

                $.ajax({
                    url: '@Url.Action("UploadFile", "FileUpload")',
                    type: 'POST',
                    data: formData,
                    contentType: false,
                    processData: false,
                    success: function (response) {
                        if (response.success) {
                            $('#uploadStatus').html('<p style="color: green;">' + response.message + '</p>');
                        } else {
                            $('#uploadStatus').html('<p style="color: red;">' + response.message + '</p>');
                        }
                    },
                    error: function () {
                        $('#uploadStatus').html('<p style="color: red;">An error occurred while uploading the file.</p>');
                    }
                });
            });
        });
    </script>
}
Explicación de la Validación del Lado del Cliente
  • HTML5 y Atributos Requeridos: El atributo required en <input type="file"> asegura que el usuario seleccione un archivo antes de enviar el formulario. Esto proporciona una validación básica del lado del cliente.

  • Mensaje de Error: <span class="text-danger" id="fileError" style="display:none;">Please select a file to upload.</span> Este elemento muestra un mensaje de error si no se selecciona un archivo y se intenta enviar el formulario. Se oculta por defecto (display: none;) y se muestra dinámicamente si es necesario.

  • jQuery para Validación: En el script de jQuery, se verifica si files.length === 0 para mostrar el mensaje de error si no se selecciona ningún archivo. Si se selecciona un archivo válido, el mensaje de error se oculta ($('#fileError').hide();).

 

Progreso de la Subida

Mostrar el progreso de la subida es una característica útil para informar al usuario sobre el estado actual de la carga de archivos, especialmente útil para archivos grandes o conexiones de red lentas.

Ejemplo de Progreso de la Subida

Para mostrar el progreso de la subida, en la vista Index.cshtmlutilizaremos la función xhr disponible en $.ajax de jQuery para obtener información sobre el progreso de la subida.

@{
    ViewData["Title"] = "File Upload Example";
}

<h2>File Upload Example</h2>

<form id="uploadForm" enctype="multipart/form-data">
    <div>
        <label for="file">Choose a file to upload:</label>
        <input type="file" id="file" name="file" accept=".txt,.pdf,.doc,.docx" required />
        <span class="text-danger" id="fileError" style="display:none;">Please select a file to upload.</span>
    </div>
    <div>
        <input type="button" id="uploadButton" value="Upload" />
    </div>
</form>

<div id="uploadProgress">
    <div id="progressBar"></div>
    <div id="progressStatus">0%</div>
</div>

<div id="uploadStatus"></div>

@section Scripts {
    <script type="text/javascript">
        $(document).ready(function () {
            $('#uploadButton').click(function () {
                
                var fileInput = $('#file')[0];
                var files = fileInput.files;
                
                if (files.length === 0) {
                    $('#fileError').show();
                    return; // Evitar enviar la solicitud si no se selecciona ningún archivo
                } else {
                    $('#fileError').hide();
                }

                var formData = new FormData();
                formData.append('file', files[0]);

                $.ajax({
                    url: '@Url.Action("UploadFile", "FileUpload")',
                    type: 'POST',
                    data: formData,
                    contentType: false,
                    processData: false,
                    xhr: function () {
                        var xhr = new window.XMLHttpRequest();
                        xhr.upload.addEventListener("progress", function (evt) {
                            if (evt.lengthComputable) {
                                var percentComplete = Math.round((evt.loaded / evt.total) * 100);
                                $('#progressBar').width(percentComplete + '%');
                                $('#progressStatus').html(percentComplete + '%');
                            }
                        }, false);
                        return xhr;
                    },
                    success: function (response) {
                        $('#progressBar').width('0%');
                        $('#progressStatus').html('0%');
                        if (response.success) {
                            $('#uploadStatus').html('<p style="color: green;">' + response.message + '</p>');
                        } else {
                            $('#uploadStatus').html('<p style="color: red;">' + response.message + '</p>');
                        }
                    },
                    error: function () {
                        $('#progressBar').width('0%');
                        $('#progressStatus').html('0%');
                        $('#uploadStatus').html('<p style="color: red;">An error occurred while uploading the file.</p>');
                    }
                });
            });
        });
    </script>
}
Explicación del Progreso de la Subida
  • Div para el Progreso de la Subida: <div id="uploadProgress">...</div> contiene dos elementos:

    • <div id="progressBar"></div>: Una barra de progreso que se llenará a medida que se cargue el archivo.
    • <div id="progressStatus">0%</div>: Muestra el porcentaje de progreso actual de la subida.
  • Evento progress de XMLHttpRequest: Utilizamos xhr: function () { ... } en $.ajax() para obtener acceso al objeto XMLHttpRequest y registrar un evento progress. Este evento se dispara mientras se envía el archivo y nos proporciona evt.loaded (cantidad de bytes cargados) y evt.total (tamaño total del archivo). Calculamos y actualizamos dinámicamente el porcentaje de progreso en #progressBar y #progressStatus.

  • Restablecimiento del Progreso: En la función success y error, restablecemos la barra de progreso y el estado de progreso a 0% una vez que la subida ha finalizado, ya sea con éxito o con error.

 

Conclusiones y Buenas Prácticas

Implementar la subida de archivos con Ajax en ASP.NET Core no solo mejora la interactividad y la eficiencia de la aplicación, sino que también garantiza la seguridad y la experiencia del usuario. La combinación de validaciones exhaustivas, retroalimentación visual durante la subida, optimización del rendimiento y prácticas de seguridad robustas son fundamentales para desarrollar aplicaciones web modernas y efectivas. Mantener un código limpio y bien documentado, además de adaptarse a las mejores prácticas emergentes, asegura un mantenimiento eficiente y continuo de la aplicación a lo largo del tiempo.

Implementar estas buenas prácticas no solo mejora la usabilidad y la seguridad, sino que también asegura que las aplicaciones puedan manejar eficazmente la carga y manipulación de archivos de manera rápida y confiable. Así, los desarrolladores pueden proporcionar a los usuarios una experiencia fluida y segura al interactuar con archivos en línea dentro del entorno de ASP.NET Core.

 

  Compartir


  Nuevo comentario

El campo Comentario es obligatorio.
El campo Nombre es obligatorio.

  Comentarios

No hay comentarios para este Post.



Utilizamos cookies propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor experiencia de navegación. Si continúa navegando consideramos que acepta su uso. Más información   Acepto