ASP .NET - Salvando imagens em um Banco de dados SQL Server (C#)


Vou  mostrar como enviar e armazenar dados binários em um banco de dados SQL Server.  Dados binários podem se apresentar em uma variedade de formas como : documentos do word, arquivos PDF, Fotos , imagens , etc.

A maneira mais usada para armazenar dados binários é no sistema de arquivos de Windows, ou seja, armazenar os dados binários como um arquivo no disco local e a outra , a que irei mostrar neste artigo é armazenar os dados binários diretamente no SQL Server.

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:

Usando o tipo de dados varbinary  do SQL Server podemos armazenar arquivos com até 2GB de tamanho, e, neste exemplo eu vou criar um página ASP .NET para efetuar o upload (envio) de arquivos .GIF ou .JPG que serão armazenados diretamente no banco de dados Fotos.mdf , mais precisamente na tabela Imagens

Para estes casos específicos o SQL Server fornece um tipo de dados especial apropriados para um grande volume de dados e neste artigo eu vou mostrar como podemos ler e gravar BLOBs - Binary Large Objects usando o SQL Server e ADO .NET.

Nota: BLOB é um acrônimo para binary large object , uma coleção de dados binários armazenados em um identidade única no SQL Server.

Estes tipos de dados, Large Objects , podem ser classificados em CLOBs - Character Large Objects ou BLOBs - Binary Large Objects e o SQL Server possui um tipo diferente de dados para cada um destes objetos. Vejamos na tabela abaixo os tipos de dados que podemos usar neste caso:

LOB Type Tipo de dadaos SQL  Server Tamanho Máximo Os tipos de dados (*) Text, NText e Image já existiam em versões anteriores do SQL Server. É recomendado que você use os novos tipos de dados : varchar(MAX), nvarchar(MAX) e  varbinary(MAX)

Observando a tabela vemos que o tipo de dados  varbinary(MAX) é o que permite tratar com imagens ou Large Binary Data.

BLOB varbinary(MAX)
Image(*)
2.147.483.647
CLOB varchar(MAX)
Text(*)
2.147.483.647
CLOB - Unicode nvarchar(MAX)
NText(*)
1.073.741.823
dados XML xml 2.147.483.647

A primeira tarefa será criar um novo web site usando o Visual Web Developer Express Edition.

Abra o VWD 2008 e no menu File selecione New Web Site, e, a seguir faça o seguinte:>

Após criar o projeto do novo web site vamos criar o banco de dados Fotos.mdf e a tabela Imagem.

No menu WebSite clique em Add New Item e faça o seguinte:

Já temos o banco de dados Fotos.mdf criado vamos agora criar a tabela Imagens.

Abra o banco de dados no DataBase Explorer e clique com o botão direito sobre o item Table e selecione Add New Table;

A seguir defina a estrutura da tabela conforme a figura abaixo onde temos:

- Campos da tabela:

O campo MIME foi definido para armazenar o tipo de dados MIME do arquivo que será enviado. Para o nosso exemplo os tipos MIME válidos serão:

Obs:  É uma boa idéia efetuar a verificação da extensão do arquivo (se é .gif, .png, etc..) e também do mime-type do arquivo, prevenindo assim de usuários mal-intencionados alterarem extensões de não imagens e fazerem o upload (ex: usuário tem um vírus com extensão .exe, altera a extensão para .jpg e faz o upload);

Extensões Multi função para Mensagens de Internet (sigla MIME do inglês Multipurpose Internet Mail Extensions) é uma norma da internet para o formato das mensagens de email. A grande maioria das mensagens de correio eletrônico são trocadas usando o protocolo SMTP e usam o formato MIME

O MIME provê mecanismos para o envio de outros tipos de informações por e-mail, incluindo caracteres não utilizados no idioma inglês, usando códigos diferentes do ASCII, assim como formatos binários contendo imagens, sons, filmes e programas. MIME é também um componente fundamental de comunicação de protocolos como o HTTP, que requer que os dados sejam transmitidos em contextos semelhantes a mensagens de email, mesmo que o dado a ser transmitido não seja realmente um e-mail.  ( http://pt.wikipedia.org/wiki/MIME)

Agora já podemos criar o formulário para efetuar o Upload dos arquivos. Para isso vamos incluir no formulário web Default.aspx,  a partir da barra de ferramentas, os controles :

A seguir defina o leiaute conforme a figura 1 abaixo no Web Form Default.aspx:(Veja ao lado o código da página)

Figura 1

Apenas para lembrar , o arquivo web.config possui a string de conexão conforme abaixo:

<connectionStrings>

<add name="ConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Fotos.mdf;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient"/>

</connectionStrings>
 

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

<title></title>

</head>

<body>

<form id="form1" runat="server">

<div><table class="style1">

<tr>

<td bgcolor="#FFFFCA" class="style2" colspan="2" style="text-align: center">

Envie somente arquivos no formato .GIF ou .JPG</td>

</tr>

<tr>

<td class="style3">Nome do Arquivo</td>

<td><asp:TextBox ID="TextBox1" runat="server" Width="214px"></asp:TextBox></td>

</tr>

<tr>

<td class="style3">Arquivo a Enviar</td>

<td><asp:FileUpload ID="fupld" runat="server" Width="218px" /></td>

</tr>

<tr>

<td>&nbsp;</td>

<td><asp:Button ID="Button1" runat="server" Text="Enviar" Width="125px" /></td>

</tr>

</table>

</div>

</form>

</body>

</html>

 

Agora no evento Click do botão de comando Enviar inclua o código a seguir:

   protected void btnEnviar_Click(object sender, EventArgs e)
    {
        if (fupld.PostedFile == null || string.IsNullOrEmpty(fupld.PostedFile.FileName) || fupld.PostedFile.InputStream == null)
        {
	lblmsg.Text = "<br />Erro - Não foi possível enviar o arquivo.<br />";
	return;
         }
        else
        {
            'obtem a extensão do arquivo enviado  
            string extensao = Path.GetExtension(fupld.PostedFile.FileName).ToLower();
	
	    string tipoArquivo = null;
                    'efetua a validação do arquivo
	    switch (extensao )
	    {
		    case ".gif":
			    tipoArquivo= "image/gif";
			    break;
		    case ".jpg":
		    case ".jpeg":
		    case ".jpe":
			    tipoArquivo= "image/jpeg";
			    break;
		    default:
                                     lblmsg.Text = "<br />Erro - tipo de arquivo inválido.<br />";
		    return;
	    }
	    using (SqlConnection Conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
	    {
		    try
		    {
			    const string SQL = "INSERT INTO [Imagens] ([nomeArquivo], [horaUpload], [MIME], [imagem]) VALUES _
                                                                                               (@nomeArquivo, @horaUpload, @MIME, @imagem)";

			    SqlCommand cmd = new SqlCommand(SQL, Conn);
                                                    cmd.Parameters.AddWithValue("@nomeArquivo", txtNomeArquivo.Text.Trim());
			    cmd.Parameters.AddWithValue("@MIME", fileType);

                                                     byte[] imageBytes = new byte[fupld.PostedFile.InputStream.Length + 1];

                                                    fupld.PostedFile.InputStream.Read(imageBytes, 0, imageBytes.Length);

			    cmd.Parameters.AddWithValue("@imagem", imageBytes);
			    cmd.Parameters.AddWithValue("@horaUpload", DateTime.Now);

                                                   lblmsg.Text = "<br />Arquivo enviado com sucesso <br />";

			    Conn.Open();
			    cmd.ExecuteNonQuery();
			    Conn.Close();
		    }
		    catch
		    {
		                 lblmsg.Text = "Erro ao enviar imagem";   
                                                 Conn.Close();
		    }
	    }
        }
    }

 

Incluímos a imagem na tabela Imagem usando a instrução SQL INSERT INTO.

Executando o projeto teremos o formulário web Default.aspx apresentado e informando o nome da imagem e clicando no botão Arquivo podemos selecionar uma imagem.

Após isso basta clicar no botão Enviar para salvar o arquivo no banco de dados;

Abrindo a tabela Imagens podemos constatar a imagem salva;

Com isso vemos que salvar imagens em um banco de dados SQL Server usando ASP .NET é uma tarefa bem simples.

Pegue o projeto completo aqui : salvaImagemBD.zip (sem a base de dados)

Acompanhe como recuperar a imagem salva neste artigo:  ASP .NET - Recuperando imagens em um Banco de dados SQL Server (C#)

Eu sei é apenas ASP .NET, mas eu gosto.

Referências:


José Carlos Macoratti