ASP .NET Core -  Armazenar Imagens no SQL Server


Neste artigo veremos como armazenar imagens no SQL Server usando o EF Core em uma aplicação ASP .NET Core.

Às vezes, você vai precisar armazenar imagens em um banco de dados ao invés de guardar as imagens como arquivos físicos, e, para isso podemos armazenar e recuperar imagens no SQL Server usando o Entity Framework Core e a ASP.NET Core.

Cada opção possui seus prós e seus contras, a seguir eu relaciono alguns motivos que podem justificar cada opção:

1 - Armazenar os dados binários como um arquivo no disco local é uma boa opção se :

O grande problema com esta solução que os dados estarão fora do banco de dados e podem perder a sincronia com os demais dados em operações de exclusão, atualização, inclusão e transferência de dados. Outro fator a considerar é que o backup deverá ser feito separado.

2 - Armazenar os dados binários diretamente no banco de dados SQL Server possui as seguinte vantagens:

Nota: Usando o tipo de dados varbinary do SQL Server podemos armazenar arquivos com até 2GB de tamanho

Neste artigo eu vou tratar apenas da segunda opção e vou usar o EF Core na abordagem Code-First em um projeto ASP .NET Core.

Então vamos ao código...

recursos usados:

  1. ASP .NET Core 3.1
  2. EF Core 3.1.6
  3. VS 2019 Community 16.6.5

Criando o projeto ASP .NET Core MVC

Abra o VS 2019 Community e crie um novo projeto via menu File-> New Project;

Selecione o template ASP .NET Core Web Application, e, Informe o nome da solução AspNet_Imagens (ou outro nome a seu gosto).

A seguir selecione .NET Core e ASP .NET Core 3.1 e marque o template Web Application e as configurações conforme figura abaixo:

Observe que não vamos definir a autenticação em nosso projeto.

Depois que o projeto foi criado, precisamos adicionar a referência aos seguintes pacotes:

Nota:  Para instalar usando a janela do Console use o comando Install-Package <nome_pacote> -version 3.1.3

Esses pacotes são necessários para realizarmos o acesso ao banco de dados SQL Server e aplicarmos o Migrations ao modelo de domínio e assim gerar o banco de dados e as tabelas.

Vamos criar a pasta images dentro da pasta wwwroot e incluir duas imagens que vamos usar no projeto.

Criando o modelo de domínio e a classe de contexto

Na pasta Models vamos criar a classe Imagem que representa nosso modelo de domínio :

public class Imagem
{
    public int ImagemId { get; set; }
    public string ImagemTitulo { get; set; }
    public byte[] ImagemDados { get; set; }
}

Note que a propriedade ImagemDados é do tipo byte[], ou seja, um array de bytes que permite armazenar dados binários.

Ainda na pasta Models vamos criar a classe de contexto AppDbContext que vai herdar de DbContext e onde vamos definir o mapeamento para da entidade para a tabela Imagens:

    public class AppDbContext : DbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
        {
        }
        public DbSet<Imagem> Imagens { get; set; }
    }

Precisamos agora registrar a classe de contexto AppDbContext no framework DI da ASP.NET Core. Isso é feito dentro do método ConfigureServices() da classe Startup :

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

Agora vamos definir a string de conexão com banco de dados SQL Server no arquivo appsettings.json:

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

Na seção ConnectionStrings você deve informar a sua string de conexão e o nome do banco de dados que deverá ser gerado no SQL Server. No exemplo eu informei o nome ImagensDB.

Aplicando o Migrations

Podemos agora aplicar o Migrations para gerar o banco de dados ImagensDB e a tabela Imagens no SQL Server.

Abra uma janela no Package Manager Console e digite os comandos:

1- add-migration Inicial  : Para criar o script de migração

2- update-database  :  Para aplicar o script no SQL Server

Podemos agora abrir o SQL Server Management Studio e verificar o banco de dados e a tabela gerados:

Agora já podemos incluir dados na tabela Imagens.

Criando o controlador ImagensController e as views

Vamos criar na pasta Controllers um controlador ImagensController onde vamos criar dois métodos Action:

  1. UploadImagem() - Salva a imagem no banco de dados ;
  2. RecuperaImagem -  Recupera a última imagem enviada e a exibe;
using AspNet_Imagens.Models;
using Microsoft.AspNetCore.Mvc;
using System;
using System.IO;
using System.Linq;
namespace AspNet_Imagens.Controllers
{
    public class ImagensController : Controller
    {
        AppDbContext db;
        public ImagensController(AppDbContext _db)
        {
            db = _db;
        }

        public IActionResult Index()
        {
            return View();
        }
        [HttpPost]
        public IActionResult UploadImagem()
        {
                foreach (var file in Request.Form.Files)
                {
                    Imagem img = new Imagem();
                    img.ImagemTitulo = file.FileName;
                    MemoryStream ms = new MemoryStream();
                    file.CopyTo(ms);
                    img.ImagemDados = ms.ToArray();
                    ms.Close();
                    ms.Dispose();
                    db.Imagens.Add(img);
                    db.SaveChanges();
                }
                ViewBag.Message = $"A Imagem foi armazenada no banco de dados !";
         
            return View("Index");
        }
        [HttpPost]
        public ActionResult RecuperarImagem()
        {
            Imagem img = db.Imagens.OrderByDescending(i => i.ImagemId)
                                    .FirstOrDefault();
            if (img != null)
            {
                string imageBase64Data = Convert.ToBase64String(img.ImagemDados);

                string imageDataURL = 
                    string.Format("data:image/jpg;base64,{0}", imageBase64Data);
                ViewBag.ImageTitle = img.ImagemTitulo;
                ViewBag.ImageDataUrl = imageDataURL;
            }
            return View("Index");
        }
    }
}

Para exibir a imagem temos que converter para o formato base64.

Na pasta Views/Imagens vamos criar a view Index.cshtml que vai permitir enviar e vai exibir a imagem:

<form asp-action="UploadImagem"
      asp-controller="Imagens"
      method="post"
      enctype="multipart/form-data">
    <img src="~/images/envarquivos.png" width="100%" />
    <hr />
    <input type="file" id="file1"
           name="file1"
           multiple="multiple" />
    <button type="submit">Enviar Arquivo(s)</button>
</form>
<hr />
<form asp-action="RecuperarImagem"
      asp-controller="Imagens"
      method="post">
    <button type="submit">Exibir Ultima Imagem enviada</button>
</form>
<hr />
<h1>@ViewBag.Message</h1>
<h1>@ViewBag.ImagemTitulo</h1>
<img src="@ViewBag.ImageDataUrl" width="100%"/>

 

Para concluir vamos ajustar a views Index.cshtml da pasta /Views/Home e o arquivo _Layout.cshtml.

Executando o projeto teremos o seguinte resultado:

Pegue o projeto aqui :  AspNet_Imagens.zip  (sem as referências)

"E percorria Jesus todas as cidades e aldeias, ensinando nas sinagogas deles, e pregando o evangelho do reino, e curando todas as enfermidades e moléstias entre o povo."
Mateus 9:35

Referências:


José Carlos Macoratti