盧小麗
摘要:在日常工作中,許多單位或企業(yè)都累積了大量的文件。如何保存和組織這些文件,如何高效地查閱和使用它們,則成了一個普遍存在的問題。為解決這一問題,用powerbuilder作為開發(fā)工具編寫了一個小軟件,通過運行特殊的SQL語句,將各種文件保存于oracle的二進制大字段中,并可以隨時查看和下載文件。
關(guān)鍵詞:文件;二進制大字段;SQL語句;powerbuilder
中圖分類號:TP311文獻標(biāo)識碼: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
在日常工作中,各單位或企業(yè)都累積了大量的文件,如WORD文檔,EXCEL文檔、多媒體文檔、圖片等。如何保存和組織這些文件,如何高效地查閱和使用它們,則成了一個普遍存在的問題。
例如:該如何分門別類地保存和組織大量文件?該如何保證每臺客戶端中看到的都是最新修改過的文件?
筆者在本單位的軟件開發(fā)中就遇到類似問題。作者所要求開發(fā)的一個軟件,要求每臺客戶端都能通過該軟件,及時上傳和瀏覽打印各種最新的文檔。
為解決這個問題,通過查閱大量資料后,筆者決定用oracle數(shù)據(jù)庫的blog字段,來解決文件的保存和查詢問題。并且用power builder作為程序開發(fā)工具,開發(fā)出一個小軟件。該軟件可以上傳各種文檔、圖像、二進制文件、多媒體文件等到oracle數(shù)據(jù)庫中,并可以隨時查看和下載。
1原理及技巧
隨著計算機技術(shù)的不斷發(fā)展和普及,數(shù)據(jù)庫,尤其是關(guān)系型數(shù)據(jù)庫,在日常工作和生活中也得到了普遍應(yīng)用。
關(guān)系型數(shù)據(jù)庫中,一般常用的字段有字符型、數(shù)值型、日期型、邏輯型等類型。但還有一種特殊的字段,是以二進制形式存放數(shù)據(jù)的,長度是0~2GB字節(jié),這就是二進制大字段。如oralce、mysql、access中的blog字段。由于數(shù)據(jù)是以最基本的二進制保存,不論其原來的數(shù)據(jù)是簡單的類型還是復(fù)雜的類型,數(shù)據(jù)庫都只當(dāng)其是一連串的二進制數(shù)據(jù),因此,就解決了各種文檔、圖像、多媒體等各種文件的存儲問題。
在powerbuilder中,主要是利用blog變量和fileread語句或filewrited語句來從文件中讀取數(shù)據(jù)或?qū)憯?shù)據(jù),再用到兩條特殊的SQL命令——UPDATEBLOB和SELECTBLOB,來跟數(shù)據(jù)庫進行交互。具體見圖1。
圖1過程圖
一個table中,blog字段不能單獨存在,至少要有一個常規(guī)字段,用來標(biāo)識一條記錄。
由于blog字段比較特殊,對其進行操作的sql語句也比較特別。
添加數(shù)據(jù)時,要先insert一個空的blog字段,再用updateblob語句將二進制數(shù)據(jù)添加進去。
導(dǎo)出數(shù)據(jù)時,用selectblob語句查詢導(dǎo)出。
例如:
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類型的變量)用其他的軟件開發(fā)工具也是類似。
2程序結(jié)果
該小程序運行后出現(xiàn)如圖2的界面,程序的代碼附在文后。
圖2運行結(jié)果圖
窗口的左半部是pb的ole控件,點擊后可以直接打開word文檔或excel文檔。對于其他類型的文件,還不支持直接打開,可下載后在操作系統(tǒng)中打開或運行。
主要程序代碼:(代碼都已測試通過)
上傳按扭的代碼
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 ; //查看數(shù)據(jù)庫中是否有同名文件
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字節(jié),要先判斷讀幾次
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字節(jié),將bolb變量內(nèi)容加起來
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變量的內(nèi)容
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(,無文件內(nèi)容!)
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) //取出默認(rèn)下載路徑
m_id=trim(st_1.text)
m_hz=right(m_id,3)
m_file=m_ml+"/aaaa."+m_hz
choose case upper(m_hz) //根據(jù)不同類型使用不同語句打開
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; //導(dǎo)出bolb字段內(nèi)容
if not isnull(b1) then
li_filenum = fileopen(m_file , streammode!, write!, shared!, replace!)
li_bytes=len(b1)
jj= filewriteex(li_filenum, b1) //將bolb變量內(nèi)容寫成文件
// filewriteex命令可以寫入大于32765字節(jié)的文件
fileclose(li_filenum)
ole_1.insertfile(m_ml + m_id) //利用ole打開文檔
ole_1.doverb(7)
filedelete(m_file)
else
messagebox(,無文件內(nèi)容!)
end if
end if
3結(jié)束語
該方法有四大優(yōu)點:
1)更新及時。若采取文件拷貝的方式,則不一定保證自己手上的文檔內(nèi)容是最新的版本。而采用在程序中下載或打開的方法,則可以保證看到的是最新更新的文件;
2)保密性強。在服務(wù)器端,文件是以二進制的形式存儲在數(shù)據(jù)庫里,比起用文件形式的存放,保密性當(dāng)然提高了很多;在客戶端,則可以在程序中設(shè)置權(quán)限,決定哪些文件給哪些人看,保密性也同樣增強了;
3)易分類保存和查詢??梢栽O(shè)置一些輔助字段,如文件類型、文件名、上傳人、上傳時間、說明及備注等,便于查詢和分類統(tǒng)計;
4)易于備份。Blog字段可以跟oracle普通的字段一起,通過exp命令導(dǎo)出,形成dmp文件進行備份;
該軟件的不足之處是Client/Server類型的程序,每臺客戶端都要安裝軟件。
參考文獻:
[1]丁鉞,廖小平.powerbuilder7.0,高級開發(fā)指南[M].北京:人民郵電出版社,2000.
[2]互聯(lián)網(wǎng)在PowerBuilder中操作BLOB數(shù)據(jù)的技巧-PB編程技巧-華軟源碼[EB/OL]. http://www.hur.cn/Article/2002/3121.html.