.comment-link {margin-left:.6em;}

Wednesday, June 29, 2005

Gerar Arquivo de Campo BLOB

Autor: Aleksandro
A Dúvida.

Boa noite,

Tio,

Estou precisando de um help, tô quebrando o raio da cabeça , mais não tô
tendo muito sucesso .....então resolvi pedir ajuda....

Tenho uma loja virtual feita em java , esta loja é de uma seguradora
...então lá elabora-se vendas em Vida em Grupo e Previdência Privada...então
o cara vai lá e preenche a proposta, cálcula e pimba se tiver tudo belezinha
.....o cara imprime esta proposta ....que pode gerar boleto caso seja a
opção dele.......é neste momento que começa o meu problema.....

Na aplicação existe uma classe em java que esta gravando este pdf no meu BD
oracle 9i, em uma coluna BLOB, pois teremos que disponibilizar todos os
pdf's emitidos durante o dia, em uma rotina em PL/SQL, porque ?

Pq o cliente tem uma aplicação interna (workflow) e esta aplicação , mostra
propostas emitidas internamente na seguradora , ou seja, o cara vende a
proposta , um departamento escaneia esta proposta , guarda em uma área e
esta aplicação busca estes arquivos e mostra para o usuário, agora eles
querem fazer isto com as propostas emitidas pela loja, então terei que fazer
da seguinte maneira:

1 - Criei uma rotina em PL/SQL que gera toda a movimentação diária da loja,
que será integrada em uma tabela dentro do meu BD, e o cliente criará um
owner com grant de select nesta tabela, para a empresa responsável pelo
workflow possa pegar estes dados e inserir na aplicação, até ae tudo bem...

porém preciso disponibilizar os pdf's gerados em uma pasta , dentro de um
diretório, onde a aplicação do workflow ou alguém proprietário desta
aplicação possa manipular estes pdf's e colocar em uma área onde possa
mostrar a qualquer usuário estas propostas emitidas ....porém tô tomando uma
surra ...estou tentando utilizar o dbms_lob..mais não estou conseguindo,
gravar estes arquivos pdf's em uma pasta dentro diretório......é possivél
fazer isto ??????

eu preciso converter estes arquivos .pdf para outra extensão ???????

Qualquer ajuda é bem-vinda ou opinião .... preciso enviar uma prévia dia
30......agora..........rs....:(....

Obrigado,

Aleks


É perfeitamente possível gerar o conteúdo que está em PDF no seu campo blob em um arquivo e não há necessidade de renomear a extensão.
Até a versão 9ir2 o ult_file tem um bug (2546782) que grava número de bytes errados para campos do tipo BLOB (binários). Esse bug foi corrigido a partir da versão 10g. Porém, na dúvida está claro o uso da versão 9i, portanto vamos ao que consegui.

O conceito foi simples, fazer ftp de mim para eu mesmo ;) -- Existe um pessoal no site oracle-base que desenvolveu uma API para fazer ftp a partir de um código pl/sql. Desta maneira, é possível carregar o seu campo BLOB para uma variável e enviá-lo para a mesma/outra máquina no diretório desejado, basta que nesta máquina esteja configurado um servidor de ftp e usuário para a trasmissão.

No exemplo a seguir, fiz no meu notebook, que não possuia ftp server - então fui no google e procurei um ftp server (free), instalei e configurei um usuário onde só havia permissão de upload vindo de um só ip, evitando portanto conexões indesejadas. Isso me tomou 15 minutos (entre procurar, configurar e levantar o ftp server) realmente muito simples.

A seguir o exemplo.

ops$marcio@ORA10G> create table t ( x blob );

Table created.

ops$marcio@ORA10G>
ops$marcio@ORA10G> host dir *.pdf
Volume in drive C has no label.
Volume Serial Number is 4064-FF3B

Directory of C:\scripts\blog\question

05/19/2004 01:38 PM 218,967 teste.pdf
1 File(s) 218,967 bytes
0 Dir(s) 4,333,289,472 bytes free

ops$marcio@ORA10G>
ops$marcio@ORA10G> create or replace directory my_files as 'C:\scripts\blog\question';

Directory created.

ops$marcio@ORA10G>
ops$marcio@ORA10G> declare
2 l_blob blob;
3 l_bfile bfile;
4 begin
5 insert into t values ( empty_blob() ) returning x into l_blob;
6 l_bfile := bfilename( 'MY_FILES', 'teste.pdf' );
7 dbms_lob.fileopen( l_bfile );
8 dbms_lob.loadfromfile( l_blob, l_bfile, dbms_lob.getlength( l_bfile ) );
9 dbms_lob.fileclose( l_bfile );
10 end;
11 /

PL/SQL procedure successfully completed.

ops$marcio@ORA10G>
ops$marcio@ORA10G> select dbms_lob.getlength(x) bytes from t;

BYTES
-------------
218967

1 row selected.


Para alinhar, até aqui crei uma tabela (t) com um único campo blob (x) e dentro do diretório /scripts/blog/question eu tenho um PDF chamado teste.pdf (um paper do SQL Model 10g). Carreguei esse arquivo para a tabela t e verifiquei o tamanho. Veja que é exatamente o mesmo como no diretório, 218967 bytes.

ops$marcio@ORA10G> declare
2 l_conn UTL_TCP.connection;
3 l_blob blob;
4 begin
5 select x into l_blob from t where rownum = 1;
6
7 l_conn := ftp.login('10.60.92.238', '21', 'marcio', 'senha');
8 ftp.binary(p_conn => l_conn);
9 ftp.put_remote_binary_data
10 (p_conn => l_conn,
11 p_file => 'novo_teste.pdf',
12 p_data => l_blob );
13 ftp.logout(l_conn);
14 utl_tcp.close_all_connections;
15 end;
16 /
220 Welcome to MPortes FTP Server
331 Password required for marcio
230 User successfully logged in.
200 Type set to BINARY
227 Entering Passive Mode (10,60,92,238,4,4)
150 Opening BINARY mode data connection for file transfer.
226 Transfer complete

PL/SQL procedure successfully completed.

ops$marcio@ORA10G>
ops$marcio@ORA10G> host dir *.pdf
Volume in drive C has no label.
Volume Serial Number is 4064-FF3B

Directory of C:\scripts\blog\question

06/29/2005 01:26 AM 218,967 novo_teste.pdf
05/19/2004 01:38 PM 218,967 teste.pdf
2 File(s) 437,934 bytes
0 Dir(s) 4,333,068,288 bytes free

No bloco acima eu, através de PL/SQL, me conecto com o MPortes FTP Server e transfiro o arquivo com outro nome (novo_teste.pdf), não houve necessidade de colocar diretório porque no momento da configuração, o usuário marcio teve o diretório default direcionado para C:\scripts\blog\question. O número de bytes é o mesmo e pude abrí-lo normalmente através do reader.

Quando estiver na versão 10g, o bug da package UTL_FILE já estará superado então basta:

ops$marcio@ORA10G> declare
2 l_output utl_file.file_type;
3 l_blob blob;
4 l_amt number default 32000;
5 l_off number default 1;
6 l_raw raw(32000);
7 l_length number;
8 begin
9 l_output := utl_file.fopen( 'MY_FILES', 'novo_teste.pdf', 'wb', 32000 );
10 select x into l_blob from t;
11 l_length := dbms_lob.getlength(l_blob);
12 loop
13 exit when l_off > l_length;
14 dbms_lob.read( l_blob, l_amt, l_off, l_raw );
15 l_off := l_off + l_amt;
16 utl_file.put_raw( l_output, l_raw, true );
17 end loop;
18
19 utl_file.fclose( l_output );
20
21 end;
22 /

PL/SQL procedure successfully completed.

ops$marcio@ORA10G>
ops$marcio@ORA10G> host dir *.pdf
Volume in drive C has no label.
Volume Serial Number is 4064-FF3B

Directory of C:\scripts\blog\question

06/29/2005 02:02 AM 218,967 novo_teste.pdf
05/19/2004 01:38 PM 218,967 teste.pdf
2 File(s) 437,934 bytes
0 Dir(s) 4,333,121,536 bytes free

Comments:
Marcio,
Meu nome é Helder estava buscando sobrer uma outra dulvida e encontrei seu artigo, gostaria de saber se poderia me ajudar.

Eu preciso pegar por uma pagina web em PL/Sql web um arquivo .jpg na maquina cliente e enviar para o servidor, para depois armazenar em um campo BLOB, gostaria de saber como faço isso, ou se consigo armazenar direto, sem colocar no servidor?
 
Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?