En muchos formularios a la hora de registrarnos nos dan la opción de elegir un imagen de perfil y posteriormente la podemos reemplazar por otra. Ahora os pregunto , ¿sabéis como se guardan esas imagen ?

Algunos pensarán que se guardarán en la base de datos. En realidad es cierto y a la vez incorrecto. ¿Por qué la contradicción en la respuesta? En primer lugar, esta forma se hacía hace varios años atrás, pero no era efectivo debido a que la imagen tenía que ser guardada en bytes . El problema reside en el caso de querer mostrar de nuevo esa imagen habría que transformar de bytes al formato de la imagen. También tenemos que tener en cuenta que la base de datos recibe otras peticiones, haciendo fácil que la base de datos deje de funcionar.

Entonces, ¿cómo se hace actualmente el almacenamiento de imágenes mediante formulario?. Las imágenes se quedan alojadas en un directorio dentro de la web similar a como almacenan los archivos css propios de una web. Lo único que se guardaría en la base de datos sería ruta para acceder a la imagen.

En nuestro caso , aprenderemos a subir imágenes en C# con un proyecto MVC.

Guardar/subir imágenes

Primero comenzamos creando un nuevo proyecto. Comprobamos que tenemos un directorio llamado wwwroot, sino existe este directorio se puede crear manualmente. Dicho directorio es el directorio donde se alojarán todos los archivos css , javascript e imágenes. Si ya lo tenemos dentro de el creamos dentro de el dos directorio: ejemplo1 y ejemplo2, los cuales usaremos durante el ejemplo.

Posteriormente, creamos un nuevo controlador para nuestro ejemplo. Ahora dentro del controlador creamos un metodo de IActionResult llamado Formulario1, el cual será usaremos para el primer ejemplo. Luego de esto, creamos la vista Formulario1 que tendrá un formulario que será de tipo POST y con enctype de tipo multipart/form-data. El formulario tendrá un único campo a rellenar de tipo file, de esta forma el usuario ya propia enviar una imagen mediante el formulario.

<form method="post" enctype="multipart/form-data">
    <div>
        <label>Elija la imagen</label>
        <input type="file" name="imagen" />
    </div>
    <button type="submit">Guardar Imagen</button>
</form>

Antes de dirigirnos al controlador nuevamente, debemos hacer hacer ciertas configuraciones. Iniciamos creando un directorio llamado Helpers dentro del proyecto, en este directorio es donde se alojarán todos los clases para ciertas configuraciones de apoyo para manejar ciertos datos en los controladores . Ahora necesitamos crear varias clase que nos harán falta para almacenar la imagen en nuestro directorio deseado.

La primera clase que debe ser creada es PathProvider, la cual será la clase encargada de resolver todas las rutas. En dicha clase, inyectamos la dependencia IWebHostEnvironment dicha dependencia nos proporcionará todos los proveedores de rutas.

Antes de continuar, creamos fuera la clase PathProvider un clase enumerada llamada Folders. ¿Es realmente necesario la clase enumerada ? No, si en un proyecto quieres colocar todas las imágenes dentro de un mismo directorio. En el caso contrario, que las quieras separar se puede usar la para especificar en que directorio guardas el/los ficheros.

public enum Folders
{
   Ejemplo1 = 0, Ejemplo2 = 1
}

Ahora, continuamos dentro de la clase PathProvider y creamos un el método MapPath quien será el encargado de proporcionarnos la rutas absoluta del directorio. Este metodo recibirá dos valor el nombre del fichero y enum Folders para decirle cual será el directorio especifico. Para finalizar con el método usamos el objeto Path, de la clase System.IO, el Combine. Este método es el encargado de crear la ruta absoluta del fichero, pero primero se le pasar por parametro la objeto inyectado IWebHostEnvironment con la propiedad WebRootPath, el directorio donde guardaremos y el nombre fichero.

Path.Combine(this.environment.WebRootPath, carpeta, Filenombre);

Posteriormente, creamos la clase UploadFile que tendrá inyectada la dependencia de PathProvider. Esta clase tiene un método SubirFichero de tipo asíncrono con un Task sin valor, siendo su equivalente a un método void, y recibiendo como parámetro IFormFile. Primero comprobamos IFormFile no esta vacío , luego capturamos el nombre de IFormFile. Con este nombre utilizamos el método MapPath de clase PathProvider para obtener la ruta donde guardar el fichero.

this.path.MapPath(filename, Folders.Ejemplo1);

Ahora, para terminar hacemos un using de un bloque de código. Primero entre los parentesis del using , en una variable guardamos un objeto FileStream que le pasamos por parametro la ruta absoluta obtenido y un FileMode del tipo Create. El cual nos permitirá que dicha imagen que le pasemos e pueda guardar. Por último, el objeto IFormFile pasado por parametro y hacemos una llamada al metodo CopyToAsync y le pasamos la variable anteriormente creada. Esta línea de código de es la que debe llevar el await para que funcione el método asíncrono.

using (var stream = new FileStream(ruta, FileMode.Create))
{
    await imagen.CopyToAsync(stream);
}

Ahora terminamos de configurar el controlador de la vista Formulario1. Creamos un método asíncrono con un Task de tipo IActionResult con el mismo nombre que el método anterior donde se ve el formulario. Pero recibe un IFormFile de la vista del formulario, para finalizar le agregamos la decoración encima del método HttpPost. Ahora hacemos la inyección de dependencia de la clase UploadFile y llamamos al método SubirFichero pasándole el objeto IFormFile. Y le colocamos a esta línea de código su respectivo await para que funcione el método asíncrono.

[HttpPost]
 public async Task<IActionResult> Formulario1(IFormFile imagen)
{
   await this.files.SubirFichero(imagen);
   return View();
}

Para finalizar, configuramos en el Startup dentro de ConfigureServices . Para hacer la inyección de dependencias usamos Singelton , ya que garantiza instanciación de una clase y se puede acceder de manera global.

services.AddSingleton<PathProvider>(); services.AddSingleton<UploadFile>();

Y lo probamos para comprobar si funciona.

Eliminar imagen

En el caso de queramos eliminar un imagen, primero creamos un metodo IActionResult llamado EliminarImagen . Como en nuestro caso no guardamos el nombre de la rutas en una base de datos, usaremos el objeto DirectoryInfo con el método GetFiles() para capturar todas los ficheros que se encuentran dentro de un directorio. Ahora recorremos array de que nos devuelve el método anterior para sacar el nombre de todos los ficheros dentro un lista de string previamente creado. Ahora esta lista la mandamos a la vista como un model.

 string directorio = this.path.MapPath(Folders.Ejemplo1);
 DirectoryInfo di = new DirectoryInfo(directorio);
 List<String> ficheros = new List<string>();
     foreach(var variable in di.GetFiles())
     {
      ficheros.Add(variable.Name);
     }

Creamos dentro del directorio Helpers la clase DeleteFile. Que tendrá inyectada la dependencia PathProvider y creamos un el método void EliminarFichero, la cual recibe por parametro un string con el nombre del fichero y enum Folders. Primero con MapPath capturamos la ruta absoluta donde se encuentra la imagen o el fichero.

Ahora con un objeto de clase File y el método Exists el cual le pasamos la ruta absoluta de la imagen comprobamos si existe. Si existe llamamos al método Delete de File para que elimine la imagen con la ruta. Normalmente para trabajos más serios o con una gran cantidad de peticiones debería ir un try cath en el caso de algún error. Pero para este ejemplo no haría falta, pero si sería recomendable su uso.

String ruta = this.path.MapPath(fotosnombre, folder);
if (File.Exists(ruta))
{
File.Delete(ruta);
}

En la vista EliminarImagen tendremos un formulario de tipo post con un select con todos los nombre de las imágenes que se encuentran dentro de un directorio. Volvemos al controlador e inyectamos la dependiencia DeleteFile. Creamos un método IActionResult EliminarImagen con la decoración HttpPost y recibirá un string del nombre del fichero a eliminar. Hacemos un llamado a la dependencia recien inyectada y al método EliminarFichero , mandamos el nombre del enviados del formulario y enviamos un enum Folders.

Eso sería todo , espero que les haya servido de ayuda este POST.

Autor: Alejandro Navaroli Sallés

Curso: Desarrollo Web Full Stack

Centro: Tajamar

Año académico: 2020-2021

GitHub: https://github.com/AlexxDan/subida_elimnacion_imagen.git

URL de Referencia

Microsoft: https://docs.microsoft.com/es-es/troubleshoot/aspnet/upload-file-to-web-site

C-Sharpcorner: https://www.c-sharpcorner.com/blogs/file-upload-application-in-asp-net-c-sharp

C-Sharpcorner subir fichero con base de datos : https://www.c-sharpcorner.com/article/asp-net-mvc-form-with-file-upload/

Microsoft GetFiles: https://docs.microsoft.com/es-es/dotnet/api/system.io.directoryinfo.getfiles?view=net-5.0

Eliminar Imagen DeCodigo: https://n9.cl/7aycq

Leave a Comment

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.