ASP .NET Core 3.1 -  Upload e exibição de imagens - I


Hoje vamos recordar como enviar e exibir imagens para o servidor em uma aplicação ASP .NET Core na versão 3.1.

Neste artigo vamos recordar como usar a tag helper Image e o recurso IFormFile.

A Tag Helper Image aprimora a tag img para fornecer um comportamento de bloqueio de cache para arquivos de imagens estáticos.

O recurso IFormFile, é uma representação de um arquivo, sendo usado para processar ou salvar o arquivo no servidor.

recursos usados:

Criando o projeto ASP .NET Core MVC

Vamos criar um novo projeto no VS 2019 Community chamado Aspnet_Upload1 usando o template :

A seguir selecione o template Web Application(Model-View-Controller) e clique em Create.

Com o projeto criado vamos criar uma pasta chamada Imagens dentro da pasta wwwroot do projeto.

Agora inclua a imagem default.jpg na pasta Imagens do projeto. Essa imagem será usada como imagem padrão.

Após criar o projeto vamos incluir a referência aos pacotes:

O primeiro será usado para acessar os dados e o segundo para poder usar os recursos do Migrations.

Precisamos definir também um modelo de domínio para tratarmos em nosso projeto. Para isso vamos usar a pasta Models do projeto e a seguir criar nesta pasta a classe Cliente com a seguinte estrutura:

    public class Cliente
    {
        public int ClienteId { get; set; } 

        [Required(ErrorMessage = "Informe o nome")]
        public string Nome { get; set; }
        [Required(ErrorMessage = "Informe a idade")]
        public int Idade { get; set; }
        [Required(ErrorMessage = "Informe o email")]
        public string Email { get; set; }
        [Required(ErrorMessage = "Selecione uma imagem")]
        public string Foto { get; set; }
    }

A seguir vamos criar o arquivo ClienteViewModel na pasta Models contendo as propriedades que iremos tratar e exibir na view:

    public class ClienteViewModel
    {
        public string Nome { get; set; }
        public int Idade { get; set; }
        public string Email { get; set; }
        public IFormFile Foto { get; set; }
    }

Aqui o tipo da propriedade Foto é IFormFile que iremos tratar quando os arquivos forem enviados.

Agora vamos definir o arquivo de contexto na pasta Models com o nome de AppDbContext:

using Microsoft.EntityFrameworkCore;
namespace Aspnet_Upload1.Models
{
    public class AppDbContext : DbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options)
            : base(options)
        {
        }
        public DbSet<Cliente> Clientes { get; set; }
    }
}

Neste arquivo definimos o contexto que vai permitir a conexão com o banco de dados SQL Server e mapeamos a entidade Cliente para a tabela Clientes

Vamos definir agora o nome do banco de dados SQL Server como Cadastro.mdf e a string de conexão no arquivo appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "ConnectionStrings": {
    "sqlConnection": "Data Source=Macoratti;Initial Catalog=Cadastro;Integrated Security=True"
  },
  "AllowedHosts": "*"
}

 

Para concluir precisamos registrar o contexto AppDbContext como um serviço no projeto.

Abrindo o arquivo Startup inclua o código abaixo no método ConfigureServices:

     public void ConfigureServices(IServiceCollection services)
      {
            services.AddDbContext<AppDbContext>(opts =>
                opts.UseSqlServer(Configuration.GetConnectionString("sqlConnection")));
            services.AddControllersWithViews();
     }

Aqui definimos o provedor do banco de dados e obtemos a string de conexão definida com o nome sqlConnection.

Agora temos tudo pronto.

Se o banco de dados existir a conexão será feita. Agora se ele não existir podemos criar usando o migrations.

Para gerar o script de migração abra uma janela no Package Manage Console e digite: add-migration Inicial

A seguir, se não houver erros, para criar o banco de dados e a tabela digite : update-database

Assim teremos o banco de dados e as tabelas criadas no SQL Server.

Criando o controlador ClientesController

Na pasta Controllers do projeto já existe o controlador HomeController que vamos ajustar para exibir alguns dados.

Vamos também ajustar o arquivo _Layout.cshtml na pasta /Views/Shared para exibir um link para o controlador ClientesController que vamos criar a seguir:

<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
   <ul class="navbar-nav flex-grow-1">
       <li class="nav-item">
              <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
       </li>
       <li class="nav-item">
             <a class="nav-link text-dark" asp-area="" asp-controller="Clientes" asp-action="Index">Clientes</a>
       </li>
    </ul>
</div>

Após isso, vamos criar um controlador chamado ClientesController na pasta Controllers do projeto. Este é um controlador do tipo MVC.

Neste arquivo inclua o código abaixo:

using Aspnet_Upload1.Models;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.IO;
using System.Threading.Tasks;
namespace Aspnet_Upload1.Controllers
{
    public class ClientesController : Controller
    {
        private readonly AppDbContext dbContext;
        private readonly IWebHostEnvironment webHostEnvironment;
        public ClientesController(AppDbContext context, IWebHostEnvironment hostEnvironment)
        {
            dbContext = context;
            webHostEnvironment = hostEnvironment;
        }
        public async Task<IActionResult> Index()
        {
            var cliente = await dbContext.Clientes.ToListAsync();
            return View(cliente);
        }
        public IActionResult Novo()
        {
            return View();
        }
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Novo(ClienteViewModel model)
        {
            if (ModelState.IsValid)
            {
                string nomeUnicoArquivo = UploadedFile(model);
                Cliente employee = new Cliente
                {
                    Nome = model.Nome,
                    Email = model.Email,
                    Idade = model.Idade,
                    Foto = nomeUnicoArquivo,
                };
                dbContext.Add(employee);
                await dbContext.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
            return View();
        }
        private string UploadedFile(ClienteViewModel model)
        {
            string nomeUnicoArquivo = null;
            if (model.Foto != null)
            {
                string pastaFotos = Path.Combine(webHostEnvironment.WebRootPath, "Imagens");
                nomeUnicoArquivo = Guid.NewGuid().ToString() + "_" + model.Foto.FileName;
                string caminhoArquivo = Path.Combine(pastaFotos, nomeUnicoArquivo);
                using (var fileStream = new FileStream(caminhoArquivo, FileMode.Create))
                {
                    model.Foto.CopyTo(fileStream);
                }
            }
            return nomeUnicoArquivo;
        }
    }
}

Neste código estamos injetando o contexto e o IWebHostEnvironment para obter a pasta raiz do projeto e montar o caminho onde vamos salvar a imagem.

Criamos o método Action [HttpPost] Index que retorna uma lista de clientes.

Temos as Action Novo , get e post, para tratar a inclusão de um novo cliente.

E o método UploadFile() é que vai receber a imagem e vai salvar na pasta Imagens com um nome definido por GUID.

Nota:  Para evitar o erro de 'SqlNullValueException: Data is Null. This method or property cannot be called on Null values.ao obter os dados dos clientes com ToListAsync() não pode haver valores NULL na coluna Foto da tabela Clientes.

Na segunda parte do artigo veremos criar as views do projeto.

"Bendito seja o Deus e Pai de nosso Senhor Jesus Cristo, o Pai das misericórdias e o Deus de toda a consolação;
Que nos consola em toda a nossa tribulação, para que também possamos consolar os que estiverem em alguma tribulação, com a consolação com que nós mesmos somos consolados por Deus."
2 Coríntios 1:3,4

Referências:


José Carlos Macoratti