quinta-feira, 12 de julho de 2007

Armazenando imagens na base de dados e exibí-la em GridView


Introduzindo imagens na base de dados e indicá-la em GridView com Handler.ashx


Introdução
Este artigo explica o método de introduzir imagens na base de dados do usuário do SQL e exibí-la em um controle do ASP.NET GridView com a ajuda de Handler.aspx.

Descrição
Você viu alguma aplicação ou Web Site sem imagens? Não, você não viu. As imagens desempenham um papel principal no desenvolvimento da aplicação da internet. Ou é um web site de HTML estático ou uma aplicação avançada de RAD, tudo é construído junto com imagens. Se sua aplicação for um site de comércio eletrônico ou portal da galeria de imagens, definitivamente você tem que sofrer para guardar as imagens em lugares diferentes com tamanhos e tipos diferentes. E não é um trabalho o fácil controlar aquelas imagens não desejadas e antigas a serem removidas da pasta de imagens. Assim o seu tempo e esforço é claramente consumindo.

Para fazer sua tarefa mais fácil, este artigo explica os métodos para armazenar as imagens no banco de dados. Há muitas vantagens de conservar as imagens na base de dados. A vantagem principal é gerência fácil das imagens. Você pode controlar o número e o tamanho das imagens armazenadas em sua base. Você pode remover todas as imagens desnecessárias da base de dados em um único comando sql e você pode fazer o backup das imagens facilmente.

Introduzindo a imagem na base de dados

Para começar, deixe-me explicar a estrutura da tabela da base de dados que vamos usar para introduzir a imagem. A tabela que você criará para armazenar a imagem deve conter uma coluna do tipo de dados IMAGE. Este tipo de dados de imagem é de dados binários Variable-length com um comprimento máximo de 2^31 - (2.147.483.647) bytes 1. Para armazenar a imagem nesta coluna nós a converteremos em um array binário com a ajuda de algumas classes do namespace IO para então introduzí-la na tabela. Para demonstração, nós vamos criar uma tabela com nome ImageGallery com as quatro colunas na seguinte estrutura:

Nome da coluna Descrição Tipo de dados
Img_Id Coluna da identidade para a identificação da imagem uniqueidentifier
Image_Content Armazenar a imagem no formato binário image
Image_Type Armazenar o formato da imagem (i.e. JPEG, GIF, PNG, etc.) varchar
Image_Size Armazenar o tamanho da imagem bigint

Depois que nós criamos a tabela na base de dados, nós podemos começar a parte de codificação.

1. Abra sua aplicação web no Visual Studio 2005, arraste um controle do Upload da arquivo e um controle da Botão na Web page.
2. No code-behind adicione o namespace System.IO.

using System.IO;

3. No evento de Button1_Click do botão, escrever o seguinte código:
if (FileUpload1.PostedFile != null && FileUpload1.PostedFile.FileName != "")
{
byte[] myimage = new byte[FileUpload1.PostedFile.ContentLength];
HttpPostedFile Image = FileUpload1.PostedFile;
Image.InputStream.Read(myimage, 0, (int)FileUpload1.PostedFile.ContentLength);


SqlConnection myConnection = new SqlConnection(“Your Connection String”);
SqlCommand storeimage = new SqlCommand("INSERT INTO ImageGallery " +"(Image_Content, Image_Type, Image_Size) " +" values (@image, @imagetype, @imagesize)", myConnection);
storeimage.Parameters.Add("@image", SqlDbType.Image, myimage.Length).Value = myimage;
storeimage.Parameters.Add("@imagetype", SqlDbType.VarChar, 100).Value = FileUpload1.PostedFile.ContentType;
storeimage.Parameters.Add("@imagesize", SqlDbType.BigInt, 99999).Value = FileUpload1.PostedFile.ContentLength;

myConnection.Open();
storeimage.ExecuteNonQuery();
myConnection.Close();
}

Para fazer o upload da imagem de qualquer local (seu HD) para o servidor, nós temos que usar o objeto de HttpPostedFile. Apontar para o arquivo enviado ao objeto de HttpPostedFile. Então o método de InputStream.Read lerá o conteúdo da imagem por uma seqüência dos bytes do Stream. Assim o myimage conterá a imagem como dados binários. Agora nós temos que passar estes dados no objeto de SqlCommand, que os introduzirá na tabela da base de dados.

Exibindo a imagem em um GridView com Handler.ashx

Até agora, o artigo explicou como introduzir imagens na base de dados. A imagem está na base de dados no formato de dados binário. Recuperar estes dados em um Web page de ASP.NET é razoavelmente fácil, mas exibí-lo não é tão simples. O problema básico é que para mostrar uma imagem em uma página aspx, você precisa adicionar um Tag da imagem que fará ligação a um arquivo de imagem através do atributo src ou você precisará pôr um controle da imagem em sua página e especificar a propriedade ImageUrl.

Por exemplo:
<asp:image Runat="server" ImageUrl="YourImageFilePath" ID="Image1" />

Infelizmente, esta solução não funcionará se você necessitar mostrar dinâmicamente dados da imagem. Embora você possa ajustar o atributo de ImageUrl no código, você não tem nenhuma maneira ajustar programmatically o conteúdo da imagem. Você poderia primeiramente gravar os dados do arquivo da imagem no HD do web server, mas essa solução seria dramaticamente mais lenta, desperdiçaria espaço, e levanta a possibilidade de erros da concorrência se os pedidos múltiplos estivessem servidos ao mesmo tempo e todos tentassem escrever o mesmo arquivo.

Nestas situações, a solução é usar um recurso separado de ASP.NET que retorne os dados binários diretamente da base de dados. Aqui a classe HTTP Handler vai nos ajudar.

O que é um Handler?

O ASP.NET HTTP Handler é uma classe simples que permita que você processe um pedido e retorne uma resposta ao browser. Simplesmente nós podemos dizer que um handler é responsável para cumprir pedidos do browser. Pode processar somente um pedido de cada vez, o que gera por sua vez o desempenho elevado. A classe handler implementa a interface IHttpHandler.

Para esta demonstração do artigo, nós exibiremos a imagem no controle GridView junto com os dados que nós armazenamos na tabela. Estão aqui as etapas requeridas para realizar isto:

1. Criar um arquivo Handler.ashx para executar a recuperação da imagem. Esta página de Handler.ashx conterá somente um método chamado ProcessRequest. Este método retornará dados binários ao pedido entrante. Neste método, nós faremos o processo normal e o retorno da recuperação de dados somente o campo de Image_Content como bytes do array.

Código de exemplo abaixo:
public void ProcessRequest (HttpContext context)
{
SqlConnection myConnection = new SqlConnection(“YourConnectionString”);
myConnection.Open();
string sql = "Select Image_Content from ImageGallery where Img_Id=@ImageId";
SqlCommand cmd = new SqlCommand(sql, myConnection);
cmd.Parameters.Add("@ImageId", SqlDbType.Int).Value = context.Request.QueryString["id"];
cmd.Prepare();
SqlDataReader dr = cmd.ExecuteReader();
dr.Read();
context.Response.ContentType = dr["Image_Type"].ToString();
context.Response.BinaryWrite((byte[])dr["Image_Content"]);
}

2. Colocar um controle GridView na página do aspx, com a uma coluna TemplateField, adicionar um controle de imagem na seção de ItemTemplate do TemplateField. Especificar a propriedade de ImageUrl como:
<asp:TemplateField>
<ItemTemplate>
<asp:Image ID="Image1" runat="server" ImageUrl='<%# "Handler.ashx?id=" + Eval("Img_Id") %>' />
</ItemTemplate>
</asp:TemplateField>
3. Agora nós podemos ligar o controle de GridView para exibir todos os registros na tabela:
GridView1.DataSource = FetchAllImagesInfo();
GridView1.DataBind ();

Antes que você ligue o GridView, você deve escrever o método de FetchAllImagesInfo para retornar todos os registros com os dados da imagem da tabela e então você tem que carregar as imagens no controle de GridView. Apenas isto. Quando você rodar seu projeto, você verá as imagens sendo carregadas no controle GridView.

public DataTable FetchAllImagesInfo())
{
string sql = "Select * from ImageGallery";
SqlDataAdapter da = new SqlDataAdapter(sql, "Your Connection String");
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}

Esta é uma explanação muito simples sobre armazenar imagens na base de dados e para recuperá-las afim de exibí-las na Web page.

Para ver nossa aplicação de amostra, clique aqui.

7 comentários:

Anônimo disse...

Muito bom artigo...

sempre deixava minhas imagens no HD, ai qndo exibia para os usuario soh colocava o caminho delas atraves da propriedade (ImageUrl, SRC).
Mais ai me pediram Hoje pra gravar as Imagens no banco.
E graças a esse artigo aprendi uma coisa nova, convesso que naum sabia usar o Handler

Grato....

Alexandre Verri disse...

amigo, sabe me dizer se na hora de recuperar os dados binários do banco sou obrigado a usar o datareader? estou usando dataset e nao esta dando certo... valewss excelente tuto

Erick Almeida disse...

Se você estiver utilizando um Dataset Tipado, a leitua é ainda mais fácil. O Dataset Tipado criará uma coluna do tipo byte[] para o campo binário.

Filipe Doblinski disse...

ótimo o artigo!!!! estava procurando EXATAMENTE isto!!!! muito obrigado

Tarcicio Andrade disse...

Cara , eu queria um código simples, para puxar a imagem correspodente ao post em visualização e exibí-la em miniatura de 100 por 100.

Gerson disse...

Como mostrar um slideshow ao clicar em uma imagem na gridview.

Estou procurando na web e só encontrei com Datalist.

Marcelo disse...

Não estou conseguindo usar, este comando, com o ODBC comand estou utilizando banco firebird 2.0 e o visual studio 2010

Neobux