0

Estoy programando un proyecto donde hay una sección de noticias, la noticia debe incluir una foto principal y una sección de galeria debajo del cuerpo de la noticia, ya tengo hecho el CRUD de la noticia con la foto principal, pero en la opción de añadir la galeria tengo un input multiple, me gustaría si alguien podría explicarme para subir los archivos multiples

Código html

          <div class="input-group" style=" margin-top: 2%; margin-bottom: 2%;">
            <input type="file" asp-for="Foto" name="Foto lang=" es"" accept="image/jpeg" class="custom-file-input" id="inputGroupFile04">
            <label class="custom-file-label" for="inputGroupFile04">Subir foto principal</label>
            <small id="name" class="form-text text-muted">(formato .jpg)</small>
        </div>

        <div class="input-group" style="margin-bottom: 4%;">
            <input type="file" asp-for="Fotos" name="Fotos" lang="es" class="custom-file-input" id="inputGroupFile04" multiple>
            <label class="custom-file-label" for="inputGroupFile04">Subir galería de fotos</label>
            <small id="name" class="form-text text-muted">(formato .jpg)</small>

Repositorio

 public void GuardarArchivo(int id, IFormFile archivo, string path)
    {
        var ruta = Path.Combine(path, "noticias", id + ".jpg");
        FileStream fs = File.Create(ruta);
        archivo.CopyTo(fs);
        fs.Close();
    }

ViewModel

    public int idNoticias { get; set; }
    public string Encabezado { get; set; }
    public DateTime Fecha { get; set; }
    public string Autor { get; set; }
    public string DescripcionCorta { get; set; }
    public string Cuerpo { get; set; }
    public string VideoURL { get; set; }

    [NotMapped]
    public IFormFile Foto { get; set; }

Controlador

    [HttpPost]
    public IActionResult AgregarNoticia(NoticiasViewModel n)
    {
        if (ModelState.IsValid)
        {
            try
            {
                NoticiasRepository noticiasRepository = new NoticiasRepository();
                var notic = noticiasRepository.GetNoticiasByNombre(n.Encabezado);

                if (notic == null)
                {
                    noticiasRepository.Insert(n);

                    if (n.Foto == null)
                    {
                        noticiasRepository.SetNoPhoto(n.idNoticias, $"{Environment.WebRootPath}");
                    }
                    else if (n.Foto.ContentType != "image/jpeg")
                    {
                        ModelState.AddModelError("", "Solo se pueden cargar imagenes JPEG.");
                        return View(n);
                    }
                    else if (n.Foto.Length > 1024 * 1024)
                    {
                        ModelState.AddModelError("", "El tamaño maximo de una imagen es de [ 1 MB ].");
                        return View(n);
                    }
                    else
                    {
                        noticiasRepository.GuardarArchivo(n.idNoticias, n.Foto, $"{Environment.WebRootPath}");
                    }

                    noticiasRepository.GuardarArchivo(n.idNoticias, n.Foto, $"{Environment.WebRootPath}");

                    return RedirectToAction("Noticias", "Administrador");
                }
                else
                {
                    ModelState.AddModelError("", "Ya existe una noticia con este nombre");
                    return View(n);
                }
            
            }
            catch (Exception ex)
            {
                ModelState.AddModelError("", ex.Message);
                return View(n);
            }
        }
        else
        {
            return View(n);
        }
    }

El crud funciona con la imagen principal y se guardan las imagenes en una carpeta llamada noticias, cada imagen se guarda con el id de la noticia publicada

2
  • Si ya estas usando el IFormFile, lo único que debe de hacer es usar una lista tipo IList<IFormFile>, me gustaría ver el código que tienes, con el que subes un solo archivo. Commented el 14 nov. 2020 a las 15:57
  • 1
    Edite mi pregunta con el código faltante, ViewModel, Repositorio y Controlador Commented el 14 nov. 2020 a las 17:52

1 respuesta 1

0

Como ya tienes toda la infraestructura hecha solo seria de modificar la clase que recibe los datos (input), en este caso ya no recibirías un IFormFile, sino que un IList<IFormFile>. Te recomiendo que hagas una carpeta por cada noticia, dentro guardas las imágenes con un correlativo, seria algo así /Id/id-0.jpge.

Ahora bien si estas guardando la ruta de las imágenes en la base lo que puedes hacer es separar las rutas por ";" o algún otro separador.

Te dejo esta clase talvez te sirve, si te fijas tiene una sobrecarga para el método Upload para que lo puedas usar con un solo file.

  public class FileService 
    {
        private readonly IWebHostEnvironment _hosting;
        public string RootDirectory { get; set; } = @"files";

        public FileService(IWebHostEnvironment hosting)
        {
            _hosting = hosting;
        }
        public Task<string> Upload(IFormFile file, string name)
        {
            if (file == null) throw new ArgumentNullException();
            return Upload(new List<IFormFile> { file }, name);
        }

        public async Task<string> Upload(IList<IFormFile> files, string name)
        {
            var filesPath = string.Empty;
            var namefile = name;
            if (files.Count != 0)
            {
                var directory = @$"{RootDirectory}/{namefile}";
                var fullPath = Path.Combine(_hosting.WebRootPath, directory);
                if (!Directory.Exists(fullPath))
                {
                    Directory.CreateDirectory(fullPath);
                }
                var count = Directory.GetFiles(fullPath)?.Length;
                foreach (var file in files)
                {
                    if (file.Length > 0)
                    {
                        var extension = Path.GetExtension(file.FileName);
                        namefile =$"{name}-{count}";
                        var filePath = @$"{namefile}{extension}";
                        await using var stream = 
                        File.Create(Path.Combine(fullPath,filePath));
                        filesPath += $"{directory}/{filePath};";
                        await file.CopyToAsync(stream);
                        count++;
                    }
                }

                filesPath = filesPath.Remove((filesPath.Length-1));
            }

            return filesPath;
        }

    }

¿No es la respuesta que buscas? Examina otras preguntas con la etiqueta o formula tu propia pregunta.