Armazenar arquivo no SQLServer

24/05/2013

0

Ola, como faz para armazenar uma arquivo no banco de dados sqlserver.
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

Wilton Júnior

Responder

Post mais votado

27/05/2013

Boa noite, segue o que me foi solicitado.

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

Guilherme Wiethaus
Responder

Mais Posts

24/05/2013

Guilherme Wiethaus

Boa tarde.

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.
Responder

27/05/2013

Wilton Júnior

Amigo Guilherme obrigado pela sua dica.
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
Responder

27/05/2013

Guilherme Wiethaus

Caro amigo,

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
Responder

27/05/2013

Wilton Júnior

Ok, Guilherme obrigado, fico no aguardo...
Responder

27/05/2013

Thiago Santana

Wilton, depende do tipo de campo que foi definido na sua tabela!
No seu banco de dados está do tipo image ou binary?
Responder

27/05/2013

Guilherme Wiethaus

companheiro Thiago o que você pode ajudar sabendo disso que perguntas? É óbvio que deveria já propor uma solução sendo um caso ou outro. Se prestar atenção na questão está mais acima do que ele precisa. Desculpe mas procure não fazer redundâncias. Eu detesto isto em forums. Desculpe meu desabafo.
Responder

27/05/2013

Thiago Santana

Guilherme estou tentando apenas ajudar!
Existe diferença entre campos Image e Binary!
Att,
Responder

27/05/2013

Wilton Júnior

Calma gente, o tipo de campo imagem é do tipo image e outro arquiv é do tipo binário.
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.
Responder

27/05/2013

Guilherme Wiethaus

OK, daqui um pouco mais estou em casa e te passo a solução para escrever imagem nos campos. Na verdade funciona o código acima, mas o que não é fácil é que quando vai passar para um controle de imagem num componente TImagem. Eu já armazenei qualquer tipo de arquivo no banco inclusive figuras. quando salvo do banco para o disco funciona corretamente,a cora quando mando exibir num componente é que o bicho pega. então torci o rabo pra fazer mas consegui. Algo que pondero porque isto ocorre. Depois te passo a função.

Abraços
Responder

27/05/2013

Wilton Júnior

Obrigado Guilherme fica tranquilo que vou dar uma olhada na sua resposta amanhã.
Pois hj vou pro buteco esfriar a cabeça.

Obrigado mesmo e "Deus Abençoe"
Responder

28/05/2013

Wilton Júnior

Guilherme obrigado deu certo.
Responder

28/05/2013

Guilherme Wiethaus

Fico feliz em poder ajudar.
Responder

Que tal ter acesso a um e-book gratuito que vai te ajudar muito nesse momento decisivo?

Ver ebook

Recomendado pra quem ainda não iniciou o estudos.

Eu quero
Ver ebook

Recomendado para quem está passando por dificuldades nessa etapa inicial

Eu quero

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar