Blog de Tecnologia desenvolvido por Thiago Campos Pereira

Blog criado para documentar e disseminar o conhecimento tecnológico adquirido por Thiago Campos Pereira e colaboradores.

quarta-feira, fevereiro 02, 2005

PowerBuilder – Armazenando fotos em um Banco de Dados

Cada vez está sendo mais comum desenvolvermos aplicações que utilizem fotos / imagens. Abaixo está um exemplo de como Armazenar e recuperar fotos no banco de dados.
Este exemplo foi feito utilizando Orace 8.1.7 e PowerBuilder 9.2 (Build 7554)

PASSO 1 – Crie uma tabela
Crie uma tabela com um campo próprio para armazenar este tipo de arquivo (geramente chamado como campo BLOB), que pode variar de acordo com o SGBD ( SQL Server/Sybase/ASE = Image ou Text; Oracle = Long ou Long Raw ou Blob ou CLOB)
No meu exemplo, criei a seguinte tabela no Oracle:

CREATE TABLE TESTE_FOTO
( CODIGO NUMBER(2) NOT NULL,
DESCRICAO VARCHAR2(100) NULL,
EXTENSAO VARCHAR2(4) NULL,
FOTO LONG RAW NULL,
CONSTRAINT PK_TESTE_FOTO PRIMARY KEY (CODIGO))

O campo EXTENSAO foi feito para resolver um problema existente na API do Oracle 8, quando recuperamos a foto para exibição.
É recomendado que você nunca crie o campo BLOB em uma tabela a parte, pois geralmente este campo ocupa muito espaço, tornando a tabela pesada para utilizar em consultas que recuperam múltiplos registros.
Um detalhe muito interessante é que o campo de FOTO tem que ser Nulo. O que vai ser explicado no passo 2.

PASSO 2 – Criar a DataWindow de Manutenção
Crie uma DataWindow atualizável com todos os campos da tabela, exceto o campo BLOB, pois ele será tratado a parte. Por isso o campo BLOB deve ser nulo, pois a inserção de registro na tabela e feita em dois passos:
1 – Inserção dos campos normais
2 – Atualização do valor do campo BLOB

PASSO 3 – Selecionando o arquivo a ser armazenado
Insira um Picture Control na sua Datawindow, que será utilizado para exibir a imagem e crie um código que permita selecionar a imagem, como no exemplo abaixo :

string docpath, docname
integer li_rtn

//Exibe janela para selecionar o arquivo
li_rtn = GetFileOpenName("Selecione a Imagem",docpath, docname, "JPEG",+ "JPEG (*.jpg),*.jpg," &
+ "BMP (*.BMP),*.BMP,All Files (*.*), *.*", "C:\", 18)

IF li_rtn < filename=" docpath" ls_picturename =" trim(DW_1.Object.P_1.Filename)" ll_aux =" len(ls_picturename)" ll_i =" ll_aux" ll_i =" 0"> 0 then
ls_extensao = mid(ls_picturename,ll_i + 1)
else
setNUll(ls_extensao)
end if

dw_1.setitem(1,"extensao",ls_extensao)

//Salva a DataWindow
dw_1.update()

//Transforma o arquivo em um valor Blob
WF_grava_arquivo( DW_1.Object.P_1.Filename, LL_BLOB)


lblb_imagem = LL_BLOB
ll_codigo = dw_1.getitemnumber(1,"codigo")

//Atualiza o valor blog no Banco de Dados
updateblob teste_foto
set foto = :lblb_imagem
where codigo = :ll_codigo;


//Finaliza a transacao
commit;


Código da função WF_GRAVA_ARQUIVO
wf_grava_arquivo (string as_arquivo, ref blob lblob_final);//verifica se o arquivo já existe, se existir, realiza o updade, caso contrario, realizar o insert
long ll_row, ll_codigo, ll_file, ll_tam
blob lblob_arquivo

//ll_codigo = long (sle_1.text)

//Carrega o arquivo
ll_file = FileOpen ( as_arquivo , StreamMode! , Read! , LockRead!)
if ll_file = -1 then
messagebox("Erro","Ocorreu um erro na abertura do arquivo",stopsign!)
return
end if

lBlob_final = blob('')
ll_tam = fileread(ll_file, lblob_arquivo)


do while (ll_tam > 0)
lBlob_final = lBlob_final + lblob_arquivo
ll_tam = fileread(ll_file, lblob_arquivo)
loop

fileclose(ll_file)


PASSO 5 – Neste passo iremos recuperar o arquivo do banco de dados e exibi-lo na DataWindow.
No SQL Server e Sybase, basta incluir um controle “Large binary/text Database Ole Object” e prencher as informações corretas (Na dúvida, consulte o Help do PowerBuilder).
Mas, a solução acima não funciona no Oracle, pois existem alguns problemas com este controle, onde os dados não são recuperados.
Para resolver este problema, eu tive que criar a seguinte solução
1 – Recupero o campo BLOB para uma variável BLOB
2 – Limpo os arquivos temporários existentes. Para isso, armazeno os nomes dos arquivos temporários gerados em um XML
3 – Crio o arquivo temporário a partir da variável BLOB. Por este motivo, eu armazeno a extensão do arquivo na hora de gravar, evitando conflitos de tipos de arquivos. Neste ponto, também armazeno o nome do mesmo no XML, para limpeza no futuro.
4 – Utilizando um Picture Control na DataWindow, exibo o arquivo temporário armazenado.

Abaixo está o código utilizado para fazer este procedimento :

long ll_rowcount
long ll_codigo, ll_file, ll_row
blob lblb_imagem, lBlob_final, lblob_arquivo
string ls_imagem, ls_path
datastore vld_datastore

//Configura DataStore de Gerenciamento de arquivos temporários
vld_datastore = create datastore
vld_datastore.dataobject = 'd_arquivos_temporarios'

ll_codigo = long(sle_1.text)

//Recupera os Registros
ll_rowcount = dw_1.retrieve (ll_codigo)

//Se existir registro, vai para o tratamento do Blob
if ll_rowcount > 0 then
//Seleciona o campo Blob
selectblob foto
into :lblb_imagem
from teste_foto
where codigo = :ll_codigo;

//Importa os dados do arquivo XML de controle de arquivos temporarios
vld_datastore.importfile(XML!,'C:\tmpfoto.xml')

//Apaga todos os arquivos temporarios existentes na máquina
for ll_row = vld_datastore.rowcount() to 1 step -1
filedelete(vld_datastore.getitemstring(ll_row,"filename"))
vld_datastore.deleterow(ll_row)
next

//gera um arquivo temporario, com a extensao original
ls_path = "c:\tmpfoto" + string(today(),"yyyymmdd")+string(now(),"hhmmssffff")+"."+dw_1.getitemstring(1,"extensao")

//Grava o nome do aquivo temporario no XML de controle
ll_row = vld_datastore.insertrow(0)
vld_datastore.setitem(ll_row,"filename",ls_path)
vld_datastore.saveas( "C:\tmpfoto.xml", XML!,true )


//Carrega o arquivo
ll_file = FileOpen ( ls_path , StreamMode! , write! , Lockwrite!, Replace!)
if ll_file = -1 then
messagebox("Erro","Ocorreu um erro na abertura do arquivo",stopsign!)
return
end if

//Lê o blob e grava um arquivo
lBlob_final = lblb_imagem

do while (len(lBlob_final) > 0)
lblob_arquivo = blobmid(lBlob_final,1,32000)
filewrite(ll_file,lblob_arquivo)
lBlob_final = blobmid(lBlob_final,32001)
loop

fileclose(ll_file)

//Exibe o arquivo temporario
DW_1.Object.P_1.Filename=ls_path


messagebox("Sucesso","Arquivo recuperad com sucesso!")
end if



Boa sorte!!!!

4 Comentários:

Às 17 setembro, 2009 11:10 , Blogger Erikson Flávio disse...

Thiago, muito bom o post. Parabéns pela disseminação do conhecimento especialmente em uma linguagem com imensa dificuldade de material na net.

 
Às 17 fevereiro, 2012 16:46 , Blogger Almeida disse...

Thiago, excelente o Post, porem sou nova no PB e já me passaram uma super tarefa de mexer com BLOB.
Fiquei com dúvida quanto ao código:IF li_rtn < filename=" docpath" ls_picturename =" trim(DW_1.Object.P_1.Filename)" ll_aux =" len(ls_picturename)" ll_i =" ll_aux" ll_i =" 0"> 0 then
ls_extensao = mid(ls_picturename,ll_i + 1) else
setNUll(ls_extensao)
end if

Está correto?

Att.,
Almeida

 
Às 05 outubro, 2015 10:28 , Blogger José Guilherme Boaventura disse...

Thiago bom dia!
Estou tentando criar uma aplicação em PB 7.0 para mostrar fotos de produtos.
Segui seu tutorial de armazenar a foto no banco de dados.
Não ocorre nenhum erro, os dados são gravados no banco usando o comando UpdateBlog.
Até aí tudo ok.

O problema está em mostrar a foto gravada no banco de dados numa datawindow. Não aparece a foto ao utilizar o OLE Object long binary. Aparece em branco, como se o conteúdo fosse vazio.
Os dados estão gravados no banco mas não aparece a imagem.
Estou gravando/lendo uma imagem bmp.

As propriedades do Ole Object aparentemente estão certas, segundo o help.
Estou utilizando uma datawindow tabular, para mostrar vários registros.

O que poderia ser?

Obrigado e até mais.

José Guilherme



 
Às 05 outubro, 2015 10:29 , Blogger José Guilherme Boaventura disse...

Thiago bom dia!
Estou tentando criar uma aplicação em PB 7.0 para mostrar fotos de produtos.
Banco de dados Sybase.
Segui seu tutorial de armazenar a foto no banco de dados.
Não ocorre nenhum erro, os dados são gravados no banco usando o comando UpdateBlog.
Até aí tudo ok.

O problema está em mostrar a foto gravada no banco de dados numa datawindow. Não aparece a foto ao utilizar o OLE Object long binary. Aparece em branco, como se o conteúdo fosse vazio.
Os dados estão gravados no banco mas não aparece a imagem.
Estou gravando/lendo uma imagem bmp.

As propriedades do Ole Object aparentemente estão certas, segundo o help.
Estou utilizando uma datawindow tabular, para mostrar vários registros.

O que poderia ser?

Obrigado e até mais.

José Guilherme



 

Postar um comentário

Assinar Postar comentários [Atom]

<< Página inicial