Fórum Extrair dados de um campo blob para disco #451312
08/08/2013
0
preciso extrair para o disco arquivos .jpg que estão salvos em um campo blob.
O banco de dados é Firebird 2.0.
Para acessa-lo estou utilizando o IBexpert.
É possível realizar este procedimento através de um comando ou de alguma função existente no IBexpert?
Desde já agradeço.
Luis Fernando
Curtir tópico
+ 0Posts
08/08/2013
Rodrigo Lacerda
olha você pode tentar :
Var
Imagem:TPicture;
SelectedFile: String;
begin
if PromptForFileName(SelectedFile,'Arquivos de Bitmap (*.bmp)|*.bmp|JPEG
(*.JPG, *.JPEG, *.JPE, *.JFIF)|*.JPG; *.JPEG; *.JPE; *.JFIF|Todos os
Arquivos (*.*)|*.*','','Localizar Fotografia ', 'C:\PROGRAMA\FOTOS\',False)
then
Begin
Imagem:= TPicture.Create();
Imagem.LoadFromFile(SelectedFile);
ClipBoard.Assign(Imagem);
DBImage1.PasteFromClipBoard;
Imagem.Free;
Exit;
End
else
begin
exit;
Imagem.Free;
End;
//ShowMessage(\'Seleção Cancelada\');
end;
Gostei + 0
12/08/2013
Vtrx
Gostei + 0
12/08/2013
Deivison Melo
begin
if OpenDialog1.Execute then
begin
edtfoto.Text:=OpenDialog1.FileName;
imgfoto.Picture.LoadFromFile(edtfoto.Text);
end;
end;
---------------------------------------------------------------------
procedure Tfrmfotos.btngravarClick(Sender:
TObject);
var imagem:Tmemorystream;
texto:TMemoryStream;
extensao:string;
begin
try
extensao:=UpperCase(ExtractFileExt(edtfoto.
Text));
if(extensao<>’.JPG’)and(extensao<>’.BMP’)
and(extensao<>’.JPEG’)then
begin
raise Exception.Create(‘Formato não
suportado!’);
Abort;
end;
imagem := Tmemorystream.Create;
texto := Tmemorystream.Create;
imgfoto.Picture.Graphic.SaveToStream(imagem);
Memo1.Lines.SaveToStream(texto);
with ClientDataSet1 do
begin
Open;
Append;
TBlobField(FieldByName(‘FOTO’)).
LoadFromStream(imagem);
TBlobField(FieldByName(‘DESCRICAO’)).
LoadFromStream(texto);
end;
finally
imagem.Free;
texto.Free;
end;
end;
-----------------------------------------------------------------------
procedure Tfrmfotos.btnvisulaizarClick(Sender:
TObject);
begin
try
frmvisualizador:=Tfrmvisualizador.Create(Self);
frmvisualizador.ShowModal;
finally
FreeAndNil(frmvisualizador);
end;
end;
-----------------------------------------------------------------------
procedure Tfrmvisualizador.leimagem;
var imagem:TStream;
texto:TStream;
Jpg:TJPEGImage;
begin
try
imagem:=TMemoryStream.Create;
texto:=TMemoryStream.Create;
Jpg:=TJPEGImage.Create;
imagem:=frmfotos.ClientDataSet1.
CreateBlobStream(frmfotos.
ClientDataSet1FOTO,bmRead);
texto:=frmfotos.ClientDataSet1.
CreateBlobStream(frmfotos.ClientDataSet1DESCRICAO,b
mRead);
Jpg.LoadFromStream(imagem);
imgvisualizacao.Picture.Assign(Jpg);
memvisualizacao.Lines.LoadFromStream(texto);
finally
imagem.Free;
texto.Free;
end;
end;
-----------------------------------------------------------------------
Gostei + 0
12/08/2013
Deivison Melo
Data da última atualização: 31/05/2003
Neste artigo, abordaremos um pouquinho sobre campos do tipo BLOB (Binary Large OBject).
Tentarei ser genérico, pois campos do tipo BLOB existem em praticamente todos os banco de dados.
Entregarei alguns exemplos de como salvar/recuperar campos do tipo BLOB usando dois métodos bastante conhecidos pelos programadores familiarizados com o Delphi :
BDE, que apesar de ter sido descontinuado pela Borland ainda é largamente utilizado para acessar Sybase, Oracle, MSSQL, Paradox, e outros.
IBX, com exclusividade para o banco de dados Interbase/Firebird.
Entendendo o Problema
Por incrível que possa parecer, o tipo BLOB é bastante recente. Ele não existia a alguns anos atrás., onde numa estrutura de dados contávamos apenas com tipos tais como : data, caractere, numérico e lógico.
Desde então, a demanda por banco de dados ficou maior, e as necessidades também mudaram. Lembro-me de que uma das mais elogiadas capacidades do Dbase era o uso do campo MEMO, usando este tipo de dado, podíamos guardar textos até 32KB, ual !!!! Isso era fantastico para a época. Talvez seja indispensável dizer que atualmente 32KB é tão curto que uma simples mensagem em HTML pode atingir esse tamanho.
Bem, você deve estar se perguntando : onde quero chegar ?
Logo após o Dbase, graças ao revolucionário Sistema Operacional da Microsoft : o Windows 3.1, alguns tipos de arquivos começaram a ganhar conteúdo multimídia. Os Banco de dados ganharam a tarefa de poder guardar em sua base, todos os tipos multimídia existentes.
Várias tipos de dados começaram a florescer : "Image" (imagem) ,"Formated Memo" (texto RTF), smallint (inteiro curto), CURRENCY (moeda) e muitos outros.
Mas tinha um problema, cada software tinha os seus tipos específicos, muitos banco de dados suportavam imagens no formato Bitmap, outros no formato PCX. Assim tínhamos que nos preocupar com o banco de dados e quais os formatos que ele suportava.
Alem disso, no auge do ambiente visual, ficavam surgindo formatos multimídia a todo instante. E os principais fabricantes de banco de dados não tinham a mesma velocidade para implementa-los em seu software.
Quando achou-se que um campo do tipo "Memo" já era suficiente, surgia a necessidade de guardar "Memos Formatados" (Formated Memo), textos do tipo Rich Text (.rtf) para guardar textos com formatação para apresentação no windows.
Quando achou-se que Bitmap era o padrão adequado para se guardar uma imagem, um formato de imagem novo e mais econômico surgiu : JPeG (.jpg), e assim por diante.
Quando Surgiu a necessidade de guardar documentos do office no banco de dados, então foi criado o campo do tipo "Olé". Percebeu onde quero chegar ? O problema constante da época é que a indústria de software não parava de promover novos formatos de mídia de dados.
Eis que chega a solução para o problema....
Para solucionar este problema, uma empresa de nome Borland criou uma solução que depois foi seguida pela maioria dos principais fabricantes de banco de dados.
Criou-se o tipo "BLOB" (Binary Large OBject), esse tipo seria apenas um recipiente para campos de origem diversas, podendo ser até mesmo objetos definidos pelo próprio usuário.
Num BLOB pode-se guardar imagem, som, textos longos, textos longos formatados, ou qualquer coisa que vinhesse a aparecer no futuro. Além disso, se um registro contivesse uma imagem, o próximo registro poderia conter um trecho musical e assim por diante. Um campo BLOB não está vinculado a nenhum tipo de dado em especifico, ele é multi-formato e variável.
De fato, o campo BLOB tornou-se então padrão industrial, no entanto, dependendo da linguagem de programação utilizada, a gravação e recuperação desses tipos de dados podem mudar. A seguir demonstrarei de modo prático como gravar e recuperar campos BLOBs usando o próprio Delphi.
Aplicando a solução 'blob' com o Delphi com qualquer banco de dados via BDE.
Para manipular campos do tipo BLOB em Delphi, é muito "fácil".
Coloquei o "fácil" entre aspas, porque é preciso saber que a manipulação de BLOBs indifere se iremos trabalhar com textos, imagens, sons ou qualquer outra coisa.
Usando o BDE juntamente com o TDatabase, os método para gravação e recuperação de um blob será sempre o mesmo.
No exemplo a seguir, vou demonstrar como guardar um Documento do Word (na verdade pode ser qualquer documento ou arquivo) num campo do tipo BLOB :
var
m : TQuery;
begin
m:=TQuery.Create(self);
m.DatabaseName:='Um\databasename\qualquer';
m.sql.add('UPDATE TABELA_TAL');
m.sql.add('SET campo_blob=:_nomearq');
m.sql.add('WHERE campo_chave =1');
try
m.ParamByName('_nomearq').LoadFromFile('C:\TEMP\TESTE.DOC',ftBlob);
m.ExecSQL;
except
on e:exception do
begin
ShowMessage(e.message);
end;
end;
end;
Como pode ver no exemplo acima, salvar um documento qualquer dentro dum BLOB é fácil. O mais dificil de se trabalhar com um BLOB é recupera-los. Por que ?
Por uma razão bem simpes : objetos BLOB não tem tamanho definido e teoricamente pode ter tamanho ilimitado. Isso é bastante interessante, no entanto, a memória de nosso computador não é ilimitado.
Por exemplo : se mandarmos nosso programa ler um Objeto BLOB de 80MB, e não tivermos 80MB de RAM livre em nosso computador para executa-lo, um erro "inesperado" irá ocorrer.
Para contornar este problema temos um objeto do Windows chamado TStream, que permite ler objetos binários (como os campos BLOB) sob-demanda, ou seja, um pedaço de cada vez. E para facilitar ainda mais, a borland resolveu criar um objeto BlobStream (parecido com o TStream) só para tratar especificamente os campos BLOBs associados à uma Querie.
Além disso, no Delphi temos variações do TStream : TFileStream, TMemoryStream e outros. Assim que descubrimos como trabalhar BLOBs usando TStream's não mais precisaremos nos preocupar se havemos ou não de usar um componente específico para manipular um tipo BLOB em especial, deveras, o TStream é capaz de tratar qualquer tipo BLOB's independente de plataforma, sistema operacional ou banco de dados.
No exemplo a seguir, vou recuperar o documento do exemplo anterior e salva-lo novamente no disco.
Para simplificar a operação vou usar o BlobStream para recuperar o campo BLOB e transferi-lo para o disco (nesse caso o TfileStream) :
var
BlobStream : TBlobStream;
FileStream : TFileStream;
m : Tquery;
begin
m:=TQuery.Create(self);
m.DatabaseName:='Um\databasename\qualquer';
m.sql.add('SELECT campo_chave, campo_blob');
m.sql.add('FROM TABELA_TAL');
m.sql.add('WHERE campo_chave =1');
// Salvando o arquivo em disco
try
m.Open;
BlobStream := TBlobStream.Create(m.Fieldbyname('campo_blob') as TBlobField, bmRead);
FileStream := TFileStream.Create('C:\TEMP\MEU_DOC.DOC', fmCreate or fmOpenWrite);
FileStream.CopyFrom(BlobStream, 0);
ShowMessage('Documento salvo em disco. Clique em [OK] para prosseguir ...');
finally
// Liberando memoria
FileStream.Free;
BlobStream.Free;
m.Free;
end;
end;
Aplicando a solução 'blob' com o Delphi acessando o Interbase/Firebird via IBX (Interbase Express)
No Interbase/Firebird tipos BLOBs tem uma espécie de qualificação, onde um blob pode ter um conteúdo binário,texto-puro ou BLR, na realidade até existem outros tipos de BLOBs, mas que não abordarei neste artigo, mas se voce quiser saber mais sobre esses tipos diferentes de BLOBs no Interbase/Firebird veja o seguinte link :
http://www.firebase.com.br/cgi-bin/firebase.cgi/artigo?ID=138
O que iremos abordar aqui será como recuperar um objeto do tipo BLOB que conterá uma fotografia usando apenas comandos da própria linguagem sem necessidade de objetos visuais ou datawares. Os componentes dataware simplificam a nossa vida é claro, mas vez ou outra talvez voce precise recuperar um conteúdo BLOB para qual ainda não existe um componente especifico para trata-lo diretamente da sua base de dados. É o caso por exemplo do TDBImage que só sabe trabalhar com TFields.
O segredo do nosso artigo é continuar a usar os TStream's.
Conforme falado antes, os TStreams são tipos de variáveis que podem manipular de modo adequado grandes objetos, muitas vezes de tamanho indeterminado.
São muitas as circunstâncias em que podemos usar variáveis do tipo TStream, em geral, para manipular objetos do tipo BLOB sem a necessidade de ficar necessitando de componentes dataware.
Vou usar no exemplo a seguir uma variação do TStream, chamada de TMemoryStream. Eu até poderia utilizar o TStream diretamente, porém como o exemplo a seguir demonstra como jogar uma fotografia diretamente para o banco de dados, o tipo TMemoryStream possui uma vantagem de nunca fazer swap em disco. É um tipo de variável que usa Bufferização como o TStream, porém faz isso sem necessitar de ficar fazendo swap em disco e como consequencia melhorando a perfomance do aplicativo.
Além disso, trabalhar com objetos na memória é vantajoso também por questões de segurança, imagine que seu objeto BLOB seja sigiloso, caso voce venha a fazer swap em disco (TStream), um efeito colateral do windows é gerar arquivos temporários com o arquivo inteiro ou parte dele, muitas vezes esses arquivos não são apagados da forma adequada, possibilitando que outros (ou voce mesmo) possa bisbilhotar o que foi manipulado.
Nota : O Exemplo a seguir funciona carregando Imagens do tipo Bitmap, no qual todas as versões de delphi são compátiveis usando TImage, no caso de voce preferir utilizar Jpeg's, TIFF ou outros formatos então ao inves de usar 'Image1.Picture.Bitmap.LoadFromStream' prefira 'Image1.Picure.LoadFromFile' retirando a propriedade Bitmap, pois com a propriedade Bitmap somente é possivel trabalhar com bitmap's. Porém ainda no final deste artigo será explicado como usar Jpeg's com LoadFromStream.
Gravando uma fotografia num campo do tipo BLOB :
var m:TIBQuery;
b:TMemoryStream;
begin
m:=TIBQuery.Create(Self);
m.Database:=MyIBXDatabase;
m.Transaction:=MyIBXDatabase.DefaultTransaction;
m.sql.clear;
m.sql.add('UPDATE TABELA_USUARIOS');
m.sql.add('SET nome=:_nome,');
m.sql.add(' cargo=:_cargo,');
m.sql.add(' bitmap_foto=:_bitmap_foto,');
m.sql.add(' last_update=CURRENT_DATE,');
m.sql.add(' last_owner=CURRENT_USER');
m.sql.add('WHERE id_usuario=1');
try
m.parambyName('_nome').AsString:='Maria Jose';
m.parambyName('_cargo').AsString:='Estagiária';
// gravando a fotografia que se encontra num TImage comum
// e transferindo-o diretamente para a tabela e sem nenhum
// swap em disco
b:=TMemoryStream.Create;
Image1.Picture.Graphic.SaveToStream(b); // Image1 é um TImage qualquer
m.ParamByName('_bitmap_foto').LoadFromStream(b,ftBlob);
m.ExecSQL;
Application.MessageBox('Dados do usuario atualizados com sucesso !','Sucesso :');
except
on e:exception do
begin
Application.MessageBox(Pchar(e.message),'Erro ao atualizar dados :');
b.Destroy;
m.Free;
Exit;
end;
end;
b.Destroy;
m.Free;
end;
O código acima transfere uma fotografia carregado num TImage para o campo do tipo BLOB sem a necessidade de nenhum swap em disco e exatamente por isso, será uma gravação mais rápida.
Além disso, o codigo acima é totalmente portável para outras ocasiões, por exemplo, imagine que voce queira transferir um arquivo que já se encontra no disco para o banco de dados, então no exemplo acima, bastaria retirar toda a referencia de TMemoryStream e fazer um simples .LoadFromFile :
var m:TIBQuery;
begin
m:=TIBQuery.Create(Self);
m.Database:=MyIBXDatabase;
m.Transaction:=MyIBXDatabase.DefaultTransaction;
m.sql.clear;
m.sql.add('UPDATE TABELA_USUARIOS');
m.sql.add('SET nome=:_nome,');
m.sql.add(' cargo=:_cargo,');
m.sql.add(' bitmap_foto=:_bitmap_foto,');
m.sql.add(' last_update=CURRENT_DATE,');
m.sql.add(' last_owner=CURRENT_USER');
m.sql.add('WHERE id_usuario=1');
try
m.parambyName('_nome').AsString:='Maria Jose';
m.parambyName('_cargo').AsString:='Estagiária';
// gravando a fotografia que se encontra num arquivo em disco
// diretamente para o banco de dados
m.ParamByName('_bitmap_foto').LoadFromFile('c:\local\do\arquivo.bmp',ftBlob);
m.ExecSQL;
Application.MessageBox('Dados do usuario atualizados com sucesso !','Sucesso :');
except
on e:exception do
begin
Application.MessageBox(Pchar(e.message),'Erro ao atualizar dados :');
m.Free;
Exit;
end;
end;
m.Free;
end;
Percebeu como é fácil realizar adaptações ?
Vamos ver agora como recupera-las ?
Recuperando uma imagem num campo do tipo BLOB :
Para recuperar um conteúdo BLOB usando o IBX é praticamente é o mesmo processo de gravação, porém inverso: transferimos o conteúdo blob para uma variável de memória (TStream) e manipulamos o objeto conforme o necessário.
O exemplo a seguir, vou recuperar uma fotografia dum campo BLOB e deposita-lo num TImage, todos talvez achem que seria mais fácil usar um TDBImage, porém note que o exemplo que irei passar poderá funcionar com outros tipos de campos BLOBs e não somente imagens. O componente dataware TDBImage apenas trabalha com imagens no formato bitmap e quanto aos outros formatos (jpeg, tiff, gif, avi.) ?
O componente TAnimate permite trabalhar com o formato .AVI, porém não existe nenhum TDBAnimate para recuperar um BLOB com este formato. É nesse tipo de situação que trabalhamos com o tipo TStream que permite recuperar um objeto blob e transferi-lo para sí mesmo e num momento mais adequado transferi-lo para um recipiente mais adequado ao formato, ou se não houver transferi-lo para disco para que possa ser manipulado por um outro aplicativo.
Este recipiente para o qual o TStream poderá transferir o objeto pode ser qualquer componente visual quer possua as propriedades : '.SaveToStream' ou '.LoadFromStream', que são praticamente todos os componentes multimídia.
Por isso é que estou insistindo em usar o modelo mais genérico com TStream, para que você possa ampliar seus horizontes.
O exemplo a seguir trabalha a possibilidade de recurar um Blob do tipo Bitmap usando LoadFromStream e sem nenhum swap em disco :
var m:TIbQuery;
b:TStream;
begin
// Primeiramente vamos apagar a imagem contida no recipiente TImage
Image1.Picture.Bitmap:=nil;
m:=TIBQuery.Create(Self);
m.Database:=MyIBXDatabase;
m.Transaction:=MyIBXDatabase.DefaultTransaction;
m.sql.clear;
m.sql.add('SELECT bitmap_foto FROM TABELA_USUARIOS');
m.sql.add('WHERE id_usuario=1');
try
m.Open;
except
on e:exception do
begin
Application.MessageBox(Pchar(e.message),'Erro ao buscar fotografia do usuario :');
Exit;
end;
end;
// transferindo a fotografia para o objeto TStream
b:=m.CreateBlobStream(m.FieldByName('bitmap_foto'),bmRead);
// agora transferindo do TStream para um recipiente TImage
Image1.Picture.Bitmap.LoadFromStream(b);
b.Destroy;
m.Free;
end;
Com o código acima recuperamos a fotografia do banco de dados sem precisar usar um TDBImage, apenas usando um TStream e copiando o conteúdo do TStream para um recipiente TImage. Algumas pessoas me contactaram por e-mail pedindo que por gentileza eu cedesse um exemplo para recuperar blobs do tipo Jpeg, pois são bem mais econômicos. Pois bem a seguir, dou um exemplo de como recuperar um blob do tipo JPeg, mas antes vou explicar a dificuldade que há com o TImage ao trabalhar outros formatos gráficos.
O windows nativamente trabalha somente com bitmaps, dessa forma o TImage já está preparado para receber um OLE, Colar,LoadFromFile,LoadFromStream de arquivos graficos disposto neste tipo de formato, se voce usar o exemplo acima para trabalhar com Jpegs notará que é perfeitamente possivel grava-los no banco de dados, no entanto, para receupera-los é bem mais dificil, por que ?
Exatamente porque o TImage só conhece nativamente bitmap, e caso voce faça um LoadFromStream a transferência das informações dizem a respeito de bitmap, qualquer outro conteúdo será tratado como bitmap, ops! mas se o registro possui um jpeg então .... o algorítimo do bitmap embutido dentro do TImage sofrerá pertubações que causarão um festival de 'access violation on...' (violação de acesso).
Como resolver essa situação ?
Uma solução simples e definitiva é trocar o LoadFromStream e passar a usar o LoadFromFile, pois oTImage associará a extensão do arquivo ao formato quese pretente usar, se por exemplo fizermos : Image1.LoadFromFile('c:\exemplo\foto1.jpg') ele saberá que '.jpg' não é um bitmap e automaticamente irá trata-lo de forma diferente e caso não possa trabalhar com o formato ele rejeitará o arquivo com uma mensagem de erro.
Mas essa solução talvez deixe alguns decepcionados, pois o LoadFromStream é muito melhor, e em alguns casos como programaçao em 'n camadas' é o único que pode ser feito. Então vamos à uma abordagem específica para carregar 'Jpegs' através de LoadFromStream.
Antes de mais nada, coloque a unit 'jpeg' na seção 'uses' de seu formulário. Vamos ao exemplo :
procedure TForm1.CarregarFotoJpeg;
var m:TIbQuery;
b:TStream;
Jpg: TJpegImage;
begin
Jpg := nil;
// carregar foto
m:=TIBQuery.Create(Self);
m.Database:=MyIBXDatabase;
m.Transaction:=MyIBXDatabase.DefaultTransaction;
m.sql.clear;
m.sql.add('SELECT jpeg_foto FROM TABELA_USUARIOS');
m.sql.add(''WHERE id_usuario=1');
try
m.Open;
except
on e:exception do
begin
Application.MessageBox(Pchar(e.message),'Erro ao buscar fotografia do usuario :');
Exit;
end;
end;
// transferindo a fotografia para o objeto TStream
b:=m.CreateBlobStream(m.FieldByName('jpeg_foto'),bmRead);
// se o registro não possui fotografia então apagaremos a imagem
// atual dentro do TImage, senão vai parecer que a fotografia seguinte
// será igual a anterior
if b.Size > 0 then
begin
// aqui ta o problema, como recuperar o jpeg do banco
// perceba que a variavel 'Jpg' é do tipo TJpegImage que por sua vez é uma classe TGraphic
// e que portanto poderá ser assinalada a propriedade Image1.Picure[.Graphic]
try
Jpg := TJpegImage.Create;
Jpg.LoadFromStream(b);
Image1.Picture.Assign(Jpg);
except
end;
end
else
begin
// Essa seria a maneira natural de eliminar um desenho dentro do
// TImage, pois se fizessemos um Image1.Picture.Graphic:=nil como
// sugerem alguns exemplos na internet, provocariamos um 'access violation',
// pois um nulo não pode ser tratado como bitmap ou jpeg.
Image1.Picture.Assign(nil);
end;
// Vamos liberar um pouco de memória
jpg.Free;
b.Destroy;
m.Free;
end;
O acrescimo da unit chamada jpeg na seção 'uses' (ex. uses jpeg) cria um novo tipo de dado derivada de TGraphic chamada TJpegImage e é exatamente com esta classe que poderemos trabalhar com Jpegs. Se voce for tentar trabalhar com Jpeg's sem primeiramente registra-lo ao TImage ele irá achar que a imagem recebida via LoadFromStream será um bitmap, e como eu disse anteriormente será um festival de 'access violation'.
Mas ainda há um outro problema, caso eu começe colocando num recipiente TImage uma iamgem ddo tipo Jpeg, todos as imagens a seguir deverão ser Jpegs também, caso voce tenha um bitmap entre eles (os registros), o bitmap será tratado como Jpeg e então ocorrerá novamente um festival de 'access violation' isso ocorrerá mesmo que você use a propriedade Image1.Picture.Bitmap específico para bitmaps e saiba de antemão quais registros são bitmaps e quais são jpeg, então qual seria a solução ?
Ou vamos passar a usar o LoadFromFile ou então teremos que adaptar o exemplo de Jpeg para trabalhar com Bitmaps, eu prefiro a segunda é claro!
Então vamos a um exemplo que também carrega bitmaps, porém ao ínves de usar Image1.Picture.Bitmap, usará um método mais seguro e livre de erros, muito semelhante ao exemplo Jpeg :
procedure TForm1.CarregarFotoJpeg;
var m:TIbQuery;
b:TStream;
Bmp: TBitmap;
begin
Bmp := nil;
// carregar foto
m:=TIBQuery.Create(Self);
m.Database:=MyIBXDatabase;
m.Transaction:=MyIBXDatabase.DefaultTransaction;
m.sql.clear;
m.sql.add('SELECT bitmap_foto FROM TABELA_USUARIOS');
m.sql.add(''WHERE id_usuario=1');
try
m.Open;
except
on e:exception do
begin
Application.MessageBox(Pchar(e.message),'Erro ao buscar fotografia do usuario :');
Exit;
end;
end;
// transferindo a fotografia para o objeto TStream
b:=m.CreateBlobStream(m.FieldByName('bitmap_foto'),bmRead);
// se o registro não possui fotografia então apagaremos a imagem
// atual dentro do TImage, senão vai parecer que a fotografia seguinte
// será igual a anterior
if b.Size > 0 then
begin
// Se voce tá acompanhando o problema perceberá que para recuperar o bitmap
// o exemplo é o mesmo usado para 'Jpeg', isso porque o tipoe TBitmap a exemplo do
// tipo TJpegImage derivam e são usados pela classe TGraphic
// e que portanto poderá ser assinalada a propriedade Image1.Picure[.Graphic]
try
Bmp := TBitmap.Create;
Bmp.LoadFromStream(b);
Image1.Picture.Assign(Bmp);
except
end;
end
else
begin
// Essa seria a maneira natural de eliminar um desenho dentro do
// TImage, pois se fizessemos um Image1.Picture.Graphic:=nil como
// sugerem alguns exemplos na internet, provocariamos um 'access violation',
// pois um nulo não pode ser tratado como bitmap ou jpeg.
Image1.Picture.Assign(nil);
end;
// Vamos liberar um pouco de memória
Bmp.Free;
b.Destroy;
m.Free;
end;
Com um pouco mais de cuidado, voce poderia criar num mesmo código os dois exemplos e tornar seus aplicativos mais homogeneos ao tratar de filtros graficos diferentes. Mas o que eu quis salientar é que qualquer classe correspondente ao TGraphic poderá ser usado juntamente com o TImage, e voce encontrará na internet units para TIFF, JPEG, GIF, etc...
TMemoryStream e TStream, por que ?
Na realidade o que eu quero mostrar com esses exemplos é que se soubermos recuperar ou salvar objetos BLOBs usando apenas TStream's e suas variantes estaremos dando um passo à liberdade de programação multi-formatos.
Se você ainda está acostumado a usar componentes dataware como TDBMemo, TDBRichText, TDBImage,... para usar com conteúdos BLOBs saiba que você ainda está no nível muito básico de programação com banco de dados.
Se alguém lhe pedisse para armazenar efeitos sonoros wave-tables num banco de dados, talvez você procurará um componente TDBWAV que não existe na palheta do Delphi e por causa disso lamente dizendo que o Delphi não trabalha com esse formato, o que na realidade é uma mentira deslavada!
Qualquer tipo de conteúdo, qualquer que seja o formato, pode ser armazenado e recuperado do banco de dados com o uso de operações simples TStream e suas variantes.
Nota do Autor :
Como pode ver, precisamos desmistificar os BLOBs, eles são muito úteis à comunidade.
Os exemplos acima poderão ser obtidos aqui.
Por enquanto é só pessoal.
Referencias:
Um outro exemplo bastante interessante de como tocar .AVI armazenados dentro do banco de dados :
http://community.borland.com/article/0,1410,16181,00.html
Estes exemplos de salvar e carregar BLOBs resumem-se a poucas linhas graças ao recurso OOP do Delphi, se tivessemos que criar um recurso parecido sem usar OOP, usando por exemplo o Visual Basic, veja como ficaria :
http://support.microsoft.com/support/kb/articles/Q103/2/57.asp
Este artigo está sob forma de licença GPL (General Public License) e pode ser reproduzido e distribuido livremente em outros tipos de mídia diferentes donde este artigo foi originalmente publicado, no entanto, atente-se para fato de que qualquer produto associado à este artigo também herdará as características GPL e também deverá ser fornecido livremente.
Para maiores esclarecimentos leia sobre a GPL em :
http://www.gnu.org/philosophy/philosophy.pt.html
Créditos:
Autor : Gladiston Santana
Data : 07-Março-2003
Home Page : www.gladisto.hpg.com.br
Acessado: 12/08/2013 às 13:52
Link:
http://www.firebase.com.br/fb/artigo.php?id=286
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)