时间:2022-07-22 07:33:00
摘要:在日常工作中,许多单位或企业都累积了大量的文件。如何保存和组织这些文件,如何高效地查阅和使用它们,则成了一个普遍存在的问题。为解决这一问题,用powerbuilder作为开发工具编写了一个小软件,通过运行特殊的SQL语句,将各种文件保存于oracle的二进制大字段中,并可以随时查看和下载文件。
关键词:文件;二进制大字段;SQL语句;powerbuilder
中图分类号:TP311文献标识码:A文章编号:1009-3044(2012)22-5271-04
Using Binary Large Field to Save all Documents Method
LU Xiao-li
(Guangxi Nanning City State Taxation Bureau , Nanning 530022, China)
Abstract: In their daily work, many units or enterprises have accumulated a lot of documents.How to store and organize these documents, how to effectively access and use them, then became a widespread problem.In order to solve this problem, using PowerBuilder as a designer tool to write a small software, by running a special SQL statements, the files are stored in the Oracle binary large field, and can be readily viewed and downloaded .
Key words: documents; binary large field; SQL statement; powerbuilder
在日常工作中,各单位或企业都累积了大量的文件,如WORD文档,EXCEL文档、多媒体文档、图片等。如何保存和组织这些文件,如何高效地查阅和使用它们,则成了一个普遍存在的问题。
例如:该如何分门别类地保存和组织大量文件?该如何保证每台客户端中看到的都是最新修改过的文件?
笔者在本单位的软件开发中就遇到类似问题。作者所要求开发的一个软件,要求每台客户端都能通过该软件,及时上传和浏览打印各种最新的文档。
为解决这个问题,通过查阅大量资料后,笔者决定用oracle数据库的blog字段,来解决文件的保存和查询问题。并且用power builder作为程序开发工具,开发出一个小软件。该软件可以上传各种文档、图像、二进制文件、多媒体文件等到oracle数据库中,并可以随时查看和下载。
1原理及技巧
随着计算机技术的不断发展和普及,数据库,尤其是关系型数据库,在日常工作和生活中也得到了普遍应用。
关系型数据库中,一般常用的字段有字符型、数值型、日期型、逻辑型等类型。但还有一种特殊的字段,是以二进制形式存放数据的,长度是0~2GB字节,这就是二进制大字段。如oralce、mysql、access中的blog字段。由于数据是以最基本的二进制保存,不论其原来的数据是简单的类型还是复杂的类型,数据库都只当其是一连串的二进制数据,因此,就解决了各种文档、图像、多媒体等各种文件的存储问题。
在powerbuilder中,主要是利用blog变量和fileread语句或filewrited语句来从文件中读取数据或写数据,再用到两条特殊的SQL命令——UPDATEBLOB和SELECTBLOB,来跟数据库进行交互。具体见图1。
图1过程图
一个table中,blog字段不能单独存在,至少要有一个常规字段,用来标识一条记录。
由于blog字段比较特殊,对其进行操作的sql语句也比较特别。
添加数据时,要先insert一个空的blog字段,再用updateblob语句将二进制数据添加进去。
导出数据时,用selectblob语句查询导出。
例如:
insert into test_photo (id,photo) values(‘01’,empty_blob())
updateblob test_photo set photo=:b1 where id=’01’( b1是pb中blog类型的变量)
selectblob photo into :b1 from test_photo where id=’01’( b1是pb中blog类型的变量)用其他的软件开发工具也是类似。
2程序结果
该小程序运行后出现如图2的界面,程序的代码附在文后。
图2运行结果图
窗口的左半部是pb的ole控件,点击后可以直接打开word文档或excel文档。对于其他类型的文件,还不支持直接打开,可下载后在操作系统中打开或运行。
主要程序代码:(代码都已测试通过)
上传按扭的代码
blob m_b1 ,m_b2
blob tot_b
string s1 ,s2,s3,file1, m_filename , m_hz
long n1,jj ,li_fnum ,li_bytes , ii,ll,loops ,nbr,m_count
ll=getfileopenname(’选择文件’,path1,file1,’’,’file(*.*),*.*’,’c:\’ )
if ll<>1 then
messagebox(’’,’没选中文件’)
return
end if
st_1.text=file1
m_filename=st_1.text
m_hz=right(file1,3)
setnull(tot_b)
setnull(m_b1)
m_count=0
select count(*) into :m_count from test_photo where id=:file1 ; //查看数据库中是否有同名文件
if m_count>1 then
messagebox(’’,’已有同名文件!’)
return
end if
li_bytes=filelength(path1)
li_fnum = fileopen(path1, streammode!)
if li_fnum>0 then
if li_bytes > 32765 then//一次只能读32765字节,要先判断读几次
if mod(li_bytes, 32765) = 0 then
loops = li_bytes/32765
else
loops = (li_bytes/32765) + 1
end if
else
loops = 1
end if
for ii = 1 to loops
jj = fileread(li_fnum, m_b1) //将文件分次读入bolb变量
tot_b=tot_b + m_b1//若大于32765字节,将bolb变量内容加起来
next
m_b2=blobmid(tot_b,1,li_bytes)
insert into test_photo (id,photo,hz) values(:m_filename,empty_blob(),:m_hz) ;//增加记录
updateblob test_photo set photo=:tot_b where id=:m_filename ; //上传bolb变量的内容
if sqlca.sqldbcode = 0 then
commit ;
messagebox("","保存成功!")
else
messagebox("sql error", sqlca.sqlerrtext)
end if
else
messagebox(’’,’无法打开文件!’)
end if
fileclose(li_fnum)
dw_1.retrieve()
下载按扭的代码
long ii,jj ,li_FileNum ,li_bytes ,loops,m_row
integer rtn
string m_id,m_hz,m_ml,s2,m_file
blob b1 ,tob_b
setnull(b1)
m_row=dw_1.getrow()
if m_row>0 then
st_1.text=dw_1.object.id[m_row]
m_ml=trim(sle_1.text)
m_id=trim(st_1.text)
m_hz=right(m_id,3)
m_file=m_ml+"/"+m_id
if DirectoryExists(m_ml)=false then
messagebox(’’,’指定下载目录不存在!’)
return
end if
messagebox(’’,’开始下载!’)
selectblob photo into :b1 from test_photo where id=:m_id;
//messagebox(’sqlca.SQLCode’,sqlca.SQLCode )
if not isnull(b1) then
li_FileNum = FileOpen(m_file , StreamMode!, Write!, Shared!, replace!)
li_bytes=len(b1)
//messagebox(’’,string(li_bytes))
jj= FileWriteex(li_FileNum, b1)
fileclose(li_FileNum)
messagebox(’’,’文件’+m_file+’下载完毕!’)
else
messagebox(’’,’无文件内容!’)
end if
end if
打开按扭的代码(先下载,再打开)
long ii,jj ,li_filenum ,li_bytes ,loops,m_row
integer rtn
string m_id,m_hz,m_ml,s2,m_file
blob b1 ,tob_b
setnull(b1)
m_row=dw_1.getrow()
if m_row>0 then
st_1.text=dw_1.object.id[m_row]
m_ml=trim(sle_1.text) //取出默认下载路径
m_id=trim(st_1.text)
m_hz=right(m_id,3)
m_file=m_ml+"/aaaa."+m_hz
choose case upper(m_hz) //根据不同类型使用不同语句打开
case ’doc’
ole_1.insertclass(’word.document’)
case ’xls’
ole_1.insertclass(’excel.sheet’)
case else
messagebox(’抱歉’,’本程序只能自动打开doc文件或xls文件,其他类型文件请下载后再在程序外打开。’)
return
end choose
selectblob photo into :b1 from test_photo where id=:m_id; //导出bolb字段内容
if not isnull(b1) then
li_filenum = fileopen(m_file , streammode!, write!, shared!, replace!)
li_bytes=len(b1)
jj= filewriteex(li_filenum, b1) //将bolb变量内容写成文件
// filewriteex命令可以写入大于32765字节的文件
fileclose(li_filenum)
ole_1.insertfile(m_ml + m_id) //利用ole打开文档
ole_1.doverb(7)
filedelete(m_file)
else
messagebox(’’,’无文件内容!’)
end if
end if
3结束语
该方法有四大优点:
1)更新及时。若采取文件拷贝的方式,则不一定保证自己手上的文档内容是最新的版本。而采用在程序中下载或打开的方法,则可以保证看到的是最新更新的文件;
2)保密性强。在服务器端,文件是以二进制的形式存储在数据库里,比起用文件形式的存放,保密性当然提高了很多;在客户端,则可以在程序中设置权限,决定哪些文件给哪些人看,保密性也同样增强了;
3)易分类保存和查询。可以设置一些辅助字段,如文件类型、文件名、上传人、上传时间、说明及备注等,便于查询和分类统计;
4)易于备份。Blog字段可以跟oracle普通的字段一起,通过exp命令导出,形成dmp文件进行备份;
该软件的不足之处是Client/Server类型的程序,每台客户端都要安装软件。
参考文献:
[1]丁钺,廖小平.powerbuilder7.0,高级开发指南[M].北京:人民邮电出版社,2000.
[2]互联网在PowerBuilder中操作BLOB数据的技巧-PB编程技巧-华软源码[EB/OL]. .