Armazenar arquivo no SQLServer
24/05/2013
0
Os arquivos a armazenar são do tipo: .doc, .xls, .xml e outros.
Serão arquivos não imagens.
Obrigado
"Deus Abençoe!"
Wilton Júnior
Post mais votado
27/05/2013
Verifique se atende a suas necessidades. Estes códigos funcionam perfeitamente usando ferramenta RAD Delphi 2007 e XE2, banco de Dados SQL Server 2008 R2 com campo declarados do tipo varbinary(MAX).
Estude as 3 funções que entenderá como aplica-los. Qualquer coisa estou a disposição.
Não esqueça de declarar a unit Graphics, jpeg;
[code]
//-----------------------------------------------------------------------------
// Data Criacao: 26/10/2012
// Data Alteracao: 26/11/2012
//
// Carrega imagem jpg, bmp, emf, wmf e ico em um componente Graphics.TPicture
// a partir de um campo BLOB de dados binaios do banco de dados.
//
// Observacao:
// - A imagem do tipo png não esta implementado.
// - Ao terminar de utilizar o componente pic, deve desalocar este para
// evitar vazamento de memoria.
//
// Exemplo:
//
// pic:= PictureFromBlobField(TBlobField(ADOA[N_Funcionarios].Fieldbyname('Foto')), 'jpg');
// ...
// pic.Free;
//
//-----------------------------------------------------------------------------
function PictureFromBlobField(Blob: TBlobField; FileType: String): Graphics.TPicture
var
imgBmp: Graphics.TBitmap;
imgJpeg: jpeg.TJPEGImage;
imgWmf: Graphics.TMetafile;
imgIco: Graphics.TIcon;
BlobStream: TStream;
procedure NilObJect(Obj: TObject);
begin
Obj:= nil;
end;
begin
try
Filetype:= Trim(FileType);
Result:= nil;
if Not Assigned(Blob) then Exit;
if (not Blob.IsNull) then begin
BlobStream := TADODAtaSet(Blob.DataSet).CreateBlobStream(Blob, bmRead);
Result:= TPicture.Create();
if filetype = 'bmp' then begin
imgBmp := Graphics.TBitmap.Create;
try
imgBmp.LoadFromStream(BlobStream);
imgBmp.PixelFormat := pf24bit;
Result.Assign(imgBmp);
finally
imgBmp.Free;
end;
end;
if (filetype = 'jpg') or (filetype = 'jpge') then begin
imgJpeg := TJPEGImage.Create;
try
imgJpeg.LoadFromStream(BlobStream);
Result.Assign(imgJpeg);
finally
imgJpeg.Free;
end;
end;
if (filetype = 'wmf') or (filetype = 'emf') then begin
imgWmf := Graphics.TMetafile.Create;
try
imgWmf.LoadFromStream(BlobStream);
Result.Assign(imgWmf);
finally
imgWmf.Free;
end;
end;
if filetype = 'ico' then begin
imgIco := Graphics.TIcon.Create;
try
imgIco.LoadFromStream(BlobStream);
Result.Assign(imgIco);
finally
imgIco.Free;
end;
end;
if filetype = 'png' then begin
try
finally
end;
end;
if filetype = '' then begin
TPicture(Result):= nil;
NilObJect(Result);
end;
BlobStream.Free;
end else begin
TPicture(Result):= nil;
NilObJect(Result);
end;
except
if Assigned(BlobStream) then BlobStream.Free;
if Assigned(Result) then Result.Free;
Result:= nil;
end;
end;
//-----------------------------------------------------------------------------
// Data Criacao: 26/10/2012
// Data Alteracao: 26/11/2012
//
// Carrega imagem jpg, bmp, emf, wmf e ico em um componente TImage a partir de
// um campo BLOB de dados binaios do banco de dados. Aimagem do tipo png não
// é implementado ainda
//
// Exemplo:
// PictureToBlobField(TBlobField(ADOA[N_Funcionarios].Fieldbyname('Foto')), 'jpg', IMGFotoFace.Picture);
//
//-----------------------------------------------------------------------------
function PictureToBlobField(Blob: TBlobField; filetype: string;
Pic: Graphics.TPicture
): Boolean; stdcall;
var
imgBmp: Graphics.TBitmap;
imgJpeg: jpeg.TJPEGImage;
imgWmf: Graphics.TMetafile;
imgIco: Graphics.TIcon;
BlobStream: TStream;
begin
try
Result:= False;
if Not Assigned(Blob) then Exit;
BlobStream := TADODAtaSet(Blob.DataSet).CreateBlobStream(Blob, bmWrite);
if filetype = 'bmp' then begin
imgBmp := Graphics.TBitmap.Create;
try
imgBmp.Assign(Pic.Graphic);
imgBmp.PixelFormat := pf24bit;
imgBmp.SaveToStream(BlobStream);
finally
if Assigned(imgBmp) then imgBmp.Free;
end;
end else
if (filetype = 'jpg') or (filetype = 'jpge') then begin
imgJpeg := TJPEGImage.Create;
try
imgJpeg.Assign(Pic.Graphic);
imgJpeg.SaveToStream(BlobStream);
finally
if Assigned(imgJpeg) then imgJpeg.Free;
end;
end else
if (filetype = 'wmf') or (filetype = 'emf') then begin
imgWmf := Graphics.TMetafile.Create;
try
imgWmf.Assign(Pic.Graphic);
imgWmf.SaveToStream(BlobStream);
finally
if Assigned(imgWmf) then imgWmf.Free;
end;
end else
if filetype = 'ico' then begin
imgIco := Graphics.TIcon.Create;
try
imgIco.Assign(Pic.Graphic);
imgIco.SaveToStream(BlobStream);
finally
if Assigned(imgIco) then imgIco.Free;
end;
end else
if filetype = 'png' then begin
Result:= False;
end else begin
Result:= False;
end;
BlobStream.Free;
Result:= True;
except
if Assigned(BlobStream) then BlobStream.Free;
end;
end;
//-----------------------------------------------------------------------------
// Data Criacao: 10/01/2013
// Data Alteracao: 10/01/2013
//
// Carrega para um ImageList imagens do formato BMP a partir de um campo Blob
// do ADODataSet.
//
// Exemplo:
//
// value_Sql:= 'SELECT * FROM TiposMeiosContatos ORDER BY Indice ASC';
// ADO:= OpenInstantDataSet(DMRH.ADOConn, value_Sql, cmdText);
//
// LoadImageListFromBlobField(IMLContatos, ADO.Fieldbyname('Figura'), $FF00FF);
//
// CloseInstantDataSet(ADO);
//
// Observacao:
// - Configure antes o componente ImageList.
// - Abra o Banco de Dados, Abra a Tabela e Ordene seus registros.
// - Somente aceita formato de imagem bmp vindo do banco de dados
//-----------------------------------------------------------------------------
function LoadImageListFromBlobField(IML: TImageList; Blob: TBlobField; MaskColor: TColor): Boolean; stdcall;
var
indice: Integer;
value_Sql: String;
value_Integer: Integer;
beg
Guilherme Wiethaus
Mais Posts
24/05/2013
Guilherme Wiethaus
Eu tenho feito isto em meu sistema e é algo maravilhoso para compartilhar documentos dentro da rede ou internet onde o banco de dados é remoto. Estou primeiro focado em resolver um problema no forum de SQL quanto a instalação do SQL server 2012 e 2008 R2 que deu problemas e não instala mais. Acho que terei que formatar a máquina e começar do zero. Entende quanto tempo se perde com isso?
Primeiro crie no sua tabela um campo do tipo varbinary(MAX), não importando o que vai dentro dele, pois armazena dados em formato binário. E recomendo um outro campo para dizer que tipo de arquivo está sendo armazenado neste campo, ideal é guardar o nome original do arquivo e um outro indicando uma chave/código para este registro.
A leitura e gravação se faz por intermédio dos métodos e propriedades das classes TBlobStream, TBlobField e TADOBlobStream.
Gravar um Arquivo para Campo VarBinary:
var fStream: TFileStream; Caminho, Arquivo: String; begin ADO.Insert; ... fStream:= TFileStream.Create(Caminho + Arquivo, fmOpenRead); fStream.Position := 0; TBlobField(ADO.FieldByName('Dados')).LoadFromStream(fStream); fStream.Free; ... ADO.FieldByName('Arquivo').AsString:= Arquivo; ... ADO.Post; end;
Ler de um Campo VarBinary para um arquivo:
var Caminho_NomeArquivo: String; begin ... Caminho_NomeArquivo:= 'C:\Temp\' + ADO.FieldByName('Arquivo').AsString; TBlobField(ADOA[N_Anexos].FieldByName('Dados')).SaveToFile(Caminho_NomeArquivo); ... end;
A Store Procedure abaixo escreve um arquivo para o banco de dados que pode ser
facilmente adaptado a sua necessidade:
/*====================================================================== Data Criacao: 01/06/2011 Data Alteracao: 01/06/2011 By Guilherme Wiethaus Realiza a atualzação do campo de Blob com registros binarios. Entrada: @Table: O nome da tabela @Field: O Campo BLOB/VARBINARY da tabela @Where: Condicao de Atualziacao. Ex. Indice = 10 @FileName: O caminho e nome do arquivo para escrever para o banco Ex. c:\temp\minhaimagem.jpg Saida: Return: 0 se sucesso ======================================================================*/ ALTER PROCEDURE [dbo].[STP_UpdateFileToBlob] ( @Table VARCHAR(50), @Field VARCHAR(50), @Where VARCHAR(MAX), @FileName VARCHAR(MAX)) AS BEGIN BEGIN TRY DECLARE @result VARCHAR(MAX); DECLARE @Sql NVARCHAR(MAX); -- Monta o SQL Dinamico SET @Sql = 'UPDATE ' + @Table + ' SET ' + @Field + ' = (SELECT BulkColumn FROM OPENROWSET(' + 'BULK ''' + @FileName + ''', SINGLE_BLOB) AS BLOB) ' + 'WHERE (' + @Where + ')'; -- Executa a SQL EXECUTE sp_executesql @Sql; RETURN 0; END TRY BEGIN CATCH -- After the appropriate rollback, echo error -- information to the caller. DECLARE @ErrorMessage NVARCHAR(4000); DECLARE @ErrorSeverity INT; DECLARE @ErrorState INT; SELECT @ErrorMessage = ERROR_MESSAGE(); SELECT @ErrorSeverity = ERROR_SEVERITY(); SELECT @ErrorState = ERROR_STATE(); RAISERROR ( @ErrorMessage, -- Message text. @ErrorSeverity, -- Severity. @ErrorState -- State. ); RETURN 1; END CATCH; END;
Abraços.
27/05/2013
Wilton Júnior
Mas não ta funcionando quando tento salvar um arquivo da erro de memoria na posicao 000000 e a imagem não ta gravando de forma nenhuma.
MIC029 é o clientdataset abaixo ta o código de como estou fazendo:
wtiparq :=0;
opendialog1.Execute;
if opendialog1.FileName <> '' then
begin
if ((UpperCase(ExtractFileExt(OpenDialog1.FileName))) = '.JPG') or ((UpperCase(ExtractFileExt(OpenDialog1.FileName))) = '.JPEG')
or ((UpperCase(ExtractFileExt(OpenDialog1.FileName))) = '.BMP') or ((UpperCase(ExtractFileExt(OpenDialog1.FileName))) = '.PNG')
or ((UpperCase(ExtractFileExt(OpenDialog1.FileName))) = '.GIF') or ((UpperCase(ExtractFileExt(OpenDialog1.FileName))) = '.TIF') then
begin
wfotpro := TMemoryStream.Create;
Image1.Picture.LoadFromFile(opendialog1.FileName);
Image1.Picture.Bitmap.SaveToStream(wfotpro);
wfotpro.Position := 0;
wtiparq := 1;
end
else
begin
wfilarq := TFileStream.Create(opendialog1.FileName,fmOpenRead);
wfilarq.Position := 0;
wtiparq := 2;
end;
if WOpc = 1 then
MIC029.Insert
else
MIC029.Edit;
MIC029codimg.Value := SeqNum('CodImg');
MIC029ordser.value := MIC010ORDSER.value;
MIC029nomimg.value := OpenDialog1.FileName;
case wtiparq of
1 : MIC029Imagem.LoadFromStream(wfotpro);
2 : TBlobField(MIC029.FieldByName('arquiv')).LoadFromStream(wfilarq);
end;
MIC029.Post;
MIC029.ApplyUpdates(-1);
wfotpro.free;
wfilarq.Free;
end;
na imagem tentei assim tb TBlobField(MIC029.FieldByName('imagem')).LoadFromStream(wfotpro); e não grava.
Não sei o que mais fazer se mudo a estrutura para SQL colocando insert into não grava o OrdSer da erro de paramentro.
Obrigado e Deus Abençoes
27/05/2013
Guilherme Wiethaus
Se me recordo bem isto acontecia comigo também. É a forma com que trabalha a carga do arquivo no componente de imagem. Eu fiz de outra maneira para contornar este problema e funciona bem.
Estou no trabalho, mas a noite se sobrar um tempo, pois também tenho projetos que desenvolvo no meu horário vago, eu pego o código que grava e recupera a imagem no banco de dados e posto aqui.
Abraços
27/05/2013
Thiago Santana
No seu banco de dados está do tipo image ou binary?
27/05/2013
Guilherme Wiethaus
27/05/2013
Thiago Santana
Existe diferença entre campos Image e Binary!
Att,
27/05/2013
Wilton Júnior
O caso é que o Guilherme me passou uma solução que eu de alguma forma não estou conseguindo fazer funcionar.
Tive que separar as gravações fazer um regasso, pois image e binario é um custo para fazer funcionar.
Guilherme aguardo sua resposta se ainda tiver interesse em me ajudar.
Tiago, olha meu primeiro post que vai entender o que eu quero dizer.
27/05/2013
Guilherme Wiethaus
Abraços
27/05/2013
Wilton Júnior
Pois hj vou pro buteco esfriar a cabeça.
Obrigado mesmo e "Deus Abençoe"
Clique aqui para fazer login e interagir na Comunidade :)