Form Builder 上传和下载大对象Blob是一个难点,本文将详细讲述。
首先创建一个数据表demo(iid number,theblob blob),然后建立以这个数据表为数据块的表单。
一、利用Form Builder内建程序上传和下载图片
表中已有一条记录,有代码但没有图片。
读入相片
read_image
declare
file_namevarchar2(80);
begin
set_block_property('demo',default_where,'iid='||:block14.code);
go_block('demo');
execute_query;
file_name:='c:\temp\123.jpg';
read_image_file(file_name,'jpg','demo.theblob');
end;
下载相片
declare
file_namevarchar2(80);
begin
set_block_property('demo',default_where,'iid='||:block14.code);
go_block('demo');
execute_query;
file_name:='c:\temp\output.jpg';
write_image_file(file_name,'jpg','demo.theblob',NO_COMPRESSION,original_depth);
end;
二、通过服务器端上传大对象文件
子程序包括服务器端子程序和客户端子程序两种类型,其中服务器端子程序是指存放在数据库中的过程、函数和包,而客户端子程序则指存放在pl/sql库中的过程、函数和包。
创建目录:
CREATE OR REPLACE DIRECTORY my_files AS ‘C;\temp’;
上传文件过程:
create or replace procedure uploadblobbybfile
as
l_blob blob;
l_bfile bfile;
begin
l_bfile := bfilename ('MY_FILES','006.jpg');
insert into demo (iid, theblob)
values (8, empty_blob())
returning theblob
into l_blob;
dbms_lob.fileopen (l_bfile);
dbms_lob.loadfromfile
(l_blob,
l_bfile,
dbms_lob.getlength (l_bfile));
dbms_lob.fileclose (l_bfile);
commit;
l_bfile := bfilename ('MY_FILES','example.doc');
insert into demo (iid, theblob)
values (9, empty_blob())
returning theblob
into l_blob;
dbms_lob.fileopen (l_bfile);
dbms_lob.loadfromfile
(l_blob,
l_bfile,
dbms_lob.getlength (l_bfile));
dbms_lob.fileclose (l_bfile);
commit;
end;
运行成功。
三、利用WebUtil上传大对象文件
declare
dirnamevarchar2(50);
filenamevarchar2(50);
filternamevarchar2(50);
titlenamevarchar2(50);
retstrvarchar2(100);
tablenamevarchar2(10);
columnnamevarchar2(10);
whereclausevarchar2(50);
progresstitlevarchar2(50);
progressubstitlevarchar2(50);
asynboolean;
calltrigvarchar2(50);
bsuccessboolean;
nknumber;
nk1number;
begin
dirname:='c:\windows\web';
filename:='abc';
filtername:='|jpg file|*.jpg|docfile|*.doc|';
titlename:='打开文件';
retstr:=webutil_file.File_Selection_Dialog(dirname,filename,filtername,titlename);
nk1:=:demo.IID;
tablename:='demo';
columnname:='theblob';
whereclause:='iid='||:demo.IID;
progresstitle:='导入文件进度条';
progressubstitle:='导入文件子进度条';
asyn:=FALSE;
calltrig:=NULL;
bsuccess:=webutil_file_transfer.Client_To_DB(retstr,tablename,columnname,whereclause,asyn,calltrig);
if bsuccess then
retstr:='成功';
:UDLOB_BY_WEBUTIL.TEXT_ITEM65:=retstr;
else
retstr:='失败';
:UDLOB_BY_WEBUTIL.TEXT_ITEM65:=retstr;
end if;
end;
运行成功,但是文件没有传输到blob中,主要是因为输入IID时,锁定了这个记录。因此这条途径不是很理想。
四、通过服务器端内建程序下载大对象文件
DOWNLOADLOBTOFILE
declare
l_lob blob;
l_amt number;
l_off number;
l_raw raw(1024);
l_varchar varchar2(1024);
kk number;
ii number;
nn number;
fileid UTL_FILE.file_type;
begin
fileid := UTL_FILE.FOPEN ('MY_FILES', '12345.txt', 'W');
select theblob into l_lob from demo where iid='24';
kk:=dbms_lob.getlength(l_lob);
DBMS_OUTPUT.PUT_LINE ('kk'||to_char(kk));
ii:=0;
l_amt:=1024;
l_off:=1;
ifkk<=ii then
dbms_lob.read( l_lob, kk, l_off, l_raw );
l_varchar:=utl_raw.cast_to_varchar2(l_raw);
utl_file.put(fileid,l_varchar);
utl_file.fflush(fileid);
else
loop
if nn<=1024 then
dbms_lob.read( l_lob, nn, l_off, l_raw );
l_varchar:=utl_raw.cast_to_varchar2(l_raw);
utl_file.put(fileid,l_varchar);
utl_file.fflush(fileid);
exit;
else
dbms_lob.read( l_lob,l_amt, l_off, l_raw );
l_varchar:=utl_raw.cast_to_varchar2(l_raw);
utl_file.put(fileid,l_varchar);
utl_file.fflush(fileid);
end if;
ii:=1024+ii;
DBMS_OUTPUT.PUT_LINE ('ii'||to_char(ii));
l_off:=ii+1;
DBMS_OUTPUT.PUT_LINE ('l_off'||to_char(l_off));
nn:=kk-ii;
DBMS_OUTPUT.PUT_LINE ('nn'||to_char(nn));
end loop;
end if;
UTL_FILE.fclose (fileid);
end;
这个过程能够下载文件,但是文件不完整,笔者认为是内建函数有bug,所以这个途径不成功!
五、通过WebUtil下载文件大对象文件
declare
dirnamevarchar2(50);
filenamevarchar2(50);
filternamevarchar2(50);
titlenamevarchar2(50);
retstrvarchar2(100);
tablenamevarchar2(10);
columnnamevarchar2(10);
whereclausevarchar2(50);
progresstitlevarchar2(50);
progressubstitlevarchar2(50);
asynboolean;
calltrigvarchar2(50);
bsuccessboolean;
nknumber;
nk1number;
begin
dirname:='c:\temp';
filename:='abc';
filtername:='|jpg file|*.jpg|docfile|*.doc|';
titlename:='打开文件';
retstr:=webutil_file.File_SAVE_Dialog(dirname,filename,filtername,titlename);
:UDLOB_BY_WEBUTIL.TEXT_ITEM67:=retstr;
nk1:=:demo.IID;
tablename:='DEMO';
columnname:='THEBLOB';
whereclause:='IID='||:demo.IID;
progresstitle:='导入文件进度条';
progressubstitle:='导入文件子进度条';
asyn:=FALSE;
calltrig:='';
bsuccess:=webutil_file_transfer.DB_To_Client(retstr,tablename,columnname,whereclause);
if bsuccess then
retstr:='成功';
:UDLOB_BY_WEBUTIL.TEXT_ITEM67:=retstr;
else
retstr:='失败';
:UDLOB_BY_WEBUTIL.TEXT_ITEM67:=retstr;
end if;
end;
运行成功!
六、总结和注意
综上所示,笔者认为通过服务器端内建程序实现大对象的上传和通过WebUtil实现大对象的下载是实现大对象上传和下载的可靠途径。
服务器端的程序可以通过sqlplus进行调试,调试时需要屏幕输出,只需每次启动sqlplus都输入以下命令即可。
SET SERVEROUTPUT ON SIZE UNLIMITED(用一个过程,不能超过2000btyes)
SET SERVEROUTPUT ON FOR WRA