轉載于http://www.iocblog.net/java/j2ee/j2ee-oracle-blob.html
最近做一個j2ee項目,需要在jsp頁面實現(xiàn)對文件的上傳和下載。很早以前就知道jdbc支持大對象(lob)的存取,以為很容易,做起來才發(fā)現(xiàn)問題多
多,讀了一大堆文章,反而沒有什么頭緒了。正如一位網友文章所講:“…網絡上的教程99%都是行不通的,連sun自己的文檔都一直錯誤……”,實際情況大
致如此了。
存取blob出現(xiàn)這么多問題,我認為大半是由數(shù)據(jù)庫開發(fā)商、應用服務器商在jdbc驅動上的不兼容性帶來的。而實際應用中,每個人的開發(fā)運行環(huán)境不
同,使得某個網友的solution沒有辦法在別人的應用中重現(xiàn),以至于罵聲一片。至于為什么會不兼容、有哪些問題,我沒有時間去弄清,這里只說說我們怎
樣解決了問題的。
基于上述原因,先列出我們的開發(fā)環(huán)境,免得有人配不出來,招人唾罵。
數(shù)據(jù)庫 oracle 9i
應用服務器 bea weblogic 8.11
開發(fā)工具 jbuilder x
在jsp實現(xiàn)文件upload/download可以分成這樣幾塊 :文件提交到形成inputsteam;inputsteam以blob格式入庫;數(shù)據(jù)從庫中讀出為inputsteam;inputstream輸出到頁面形成下載文件。先說blob吧。
1.blob入庫
(1)直接獲得數(shù)據(jù)庫連接的情況
這是oracle提供的標準方式,先插入一個空blob對象,然后update這個空對象。代碼如下:
//得到數(shù)據(jù)庫連接(驅動包是weblogic的,沒有下載任何新版本)
class.forname("oracle.jdbc.driver.oracledriver");
connection con = drivermanager.getconnection(
"jdbc:oracle:thin:@localhost:1521:testdb", "test", "test");
//處理事務
con.setautocommit(false);
statement st = con.createstatement();
//插入一個空對象
st.executeupdate("insert into blobimg values(103,empty_blob())");
//用for update方式鎖定數(shù)據(jù)行
resultset rs = st.executequery(
"select contents from blobimg where id=103 for update");
if (rs.next()) {
//得到java.sql.blob對象,然后cast為oracle.sql.blob
oracle.sql.blob blob = (oracle.sql.blob) rs.getblob(1).;
//到數(shù)據(jù)庫的輸出流
outputstream outstream = blob.getbinaryoutputstream();
//這里用一個文件模擬輸入流
file file = new file("d:"proxy.txt");
inputstream fin = new fileinputstream(file);
//將輸入流寫到輸出流
byte[] b = new byte[blob.getbuffersize()];
int len = 0;
while ( (len = fin.read(b)) != -1) {
outstream.write(b, 0, len);
//blob.putbytes(1,b);
}
//依次關閉(注意順序)
fin.close();
outstream.flush();
outstream.close();
con.commit();
con.close();
(2)通過jndi獲得數(shù)據(jù)庫連接
在weblogic中配置到oracle的jdbc connection pool和datasource,綁定到context中,假定綁定名為”orads”。
為了得到數(shù)據(jù)庫連接,做一個連接工廠,主要代碼如下:
context context = new initialcontext();
ds = (datasource) context.lookup("orads");
return ds.getconnection();
以下是blob寫入數(shù)據(jù)庫的代碼:
connection con = connectionfactory.getconnection();
con.setautocommit(false);
statement st = con.createstatement();
st.executeupdate("insert into blobimg values(103,empty_blob())");
resultset rs = st.executequery(
"select contents from blobimg where id=103 for update");
if (rs.next()) {
//上面代碼不變
//這里不能用oracle.sql.blob,會報classcast 異常
weblogic.jdbc.vendor.oracle.oraclethinblobblob = (weblogic.jdbc.vendor.oracle.oraclethinblob) rs.getblob(1);
//以后代碼也不變
outputstream outstream = blob.getbinaryoutputstream();
file file = new file("d:"proxy.txt");
inputstream fin = new fileinputstream(file);
byte[] b = new byte[blob.getbuffersize()];
int len = 0;
while ( (len = fin.read(b)) != -1) {
outstream.write(b, 0, len);
}
fin.close();
outstream.flush();
outstream.close();
con.commit();
con.close();
2.blob出庫
從數(shù)據(jù)庫中讀出blob數(shù)據(jù)沒有上述由于連接池的不同帶來的差異,只需要j2se的標準類java.sql.blob就可以取得輸出流(注意區(qū)別java.sql.blob和oracle.sql.blob)。代碼如下:
connection con = connectionfactory.getconnection();
con.setautocommit(false);
statement st = con.createstatement();
//這里的sql語句不再需要”for update”
resultset rs = st.executequery(
"select contents from blobimg where id=103 ");
if (rs.next()) {
java.sql.blob blob = rs.getblob(1);
inputstream ins = blob.getbinarystream();
//用文件模擬輸出流
file file = new file("d:"output.txt");
outputstream fout = new fileoutputstream(file);
//下面將blob數(shù)據(jù)寫入文件
byte[] b = new byte[1024];
int len = 0;
while ( (len = ins.read(b)) != -1) {
fout.write(b, 0, len);
}
//依次關閉
fout.close();
ins.close();
con.commit();
con.close();
3.從jsp頁面提交文件到數(shù)據(jù)庫
(1)提交頁面的代碼如下:
<form action="handle.jsp" enctype="multipart/form-data" method="post" >
<input type="hidden" name="id" value="103"/>
<input type="file" name="filetoupload">
<input type="submit" value="upload">
</form>
(2)由于jsp沒有提供文件上傳的處理能力,只有使用第三方的開發(fā)包。網絡上開源的包有很多,我們這里選擇apache
jakarta的fileupload,在http:
//jakarta.apache.org/commons/fileupload/index.html
可以得到下載包和完整的api文檔。法奧為adajspexception
處理頁面(handle.jsp)的代碼如下
<%
boolean ismultipart = fileupload.ismultipartcontent(request);
if (ismultipart) {
// 建立一個新的upload對象
diskfileupload upload = new diskfileupload();
// 設置上載文件的參數(shù)
//upload.setsizethreshold(yourmaxmemorysize);
//upload.setsizemax(yourmaxrequestsize);
string rootpath = getservletconfig().getservletcontext().getrealpath("/") ;
upload.setrepositorypath(rootpath+""uploads");
// 分析request中的傳來的文件流,返回item的集合,
// 輪詢items,如果不是表單域,就是一個文件對象。
list items = upload.parserequest(request);
iterator iter = items.iterator();
while (iter.hasnext()) {
fileitem item = (fileitem) iter.next();
//如果是文件對象
if (!item.isformfield()) {
//如果是文本文件,可以直接顯示
//out.println(item.getstring());
//將上載的文件寫到服務器的web-infwebstart下,文件名為test.txt
//file uploadedfile = new file(rootpath+""uploads"test.txt");
//item.write(uploadedfile);
//下面的代碼是將文件入庫(略):
//注意輸入流的獲取
…
inputstream uploadedstream = item.getinputstream();
…
}
//否則是普通表單
else{
out.println("fieldname: " + item.getfieldname()+"<br>");
out.println("value: "+item.getstring()+"<br>"); }
}
}
%>
4.從數(shù)據(jù)庫讀取blob然后保存到客戶端磁盤上
這段代碼有點詭異,執(zhí)行后將會彈出文件保存對話窗口,將blob數(shù)據(jù)讀出保存到本地
轉載于http://hi.baidu.com/baileyfu/blog/item/373ad8436ea594149313c63b.html
JSF導航帶參數(shù)
2008年04月23日 星期三 下午 05:54
在jsf的配置文件faces-config.xml中,導航通常是導到不能帶參數(shù)的頁面,這在某些情況會造成一些浪費,就是說你不得不寫一些沒有太多用處的頁面,舉例來說:
<navigation-rule>
<from-view-id>/login.jsp</from-view-id>
<navigation-case>
<from-outcome>succeed</from-outcome>
<to-view-id>/loginsuccess.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>fail</from-outcome>
<to-view-id>/loginfail.jsp</to-view-id>
</navigation-case>
</navigation-rule>
通常在loginfail.jsp中可能并沒有什么實際的內容,只是告訴用戶登錄失敗請重新登錄,當然,有人會說,可以直接把登錄失敗 導航至loginsuccess.jsp上,然后通過<h:message>來顯示失敗信息,這樣有時候會造成其他的一些問題。我們可以采取 另外一種方法,讓登錄失敗后返回loginsuccess.jsp時帶上參數(shù)來標明失敗的原因:
首先,在loginBean的驗證登錄的方法里,定義:帳戶錯誤返回1,驗證碼錯誤返回2,全部正確返回0,然后通過FacesContext的重定向方法來跳轉并帶參數(shù),如下:
LoginBean:
public String login() {
String result = "";
int ret = authenticate(username,pwd,verifyingcode);
if(ret == 0) result = "succeed";
else
{
switch (ret) {
case 1:
result = "login.jsf?result=wrongpwd";break;
case 2:
result = "login.jsf?result=wrongcode";break;
}
try {
FacesContext.getCurrentInstance().getExternalContext().redirect(result);//重定向
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
此時,還要注意faces-config.xml中配置的變化,去掉原來fail的導航,只保留succeed的導航即可。
這樣,在loginsuccess.jsp中就可以獲取result參數(shù)來做一些諸如alert的提示了。
一、修復Windows 98/XP雙系統(tǒng)啟動菜單
1.修復前,在BIOS中設置從光驅啟動。用Windows XP安裝盤啟動電腦,在加載必要的驅動后,出現(xiàn)Windows XP的安裝界面。有三個選項:
(1)要現(xiàn)在開始安裝Windows XP,請按“Enter”鍵。
(2)要用“恢復控制臺”修復Windows XP安裝,按“R”鍵。
(3)要退出安裝程序,不安裝Windows XP,按“F3”鍵;
2. 按“R”鍵,進入“Microsoft Windows XP (TM) 故障恢復控制臺”界面;故障恢復控制臺提供系統(tǒng)修復和故障恢復功能。系統(tǒng)這時會搜尋已安裝的Windows XP系統(tǒng)文件,然后顯示搜尋結果,并詢問“要登錄到哪個Windows XP安裝(要取消,請按Enter)”,選擇1. Dindows,回車,系統(tǒng)會再詢問“管理員密碼”,再鍵入安裝Windows XP時設置的管理員密碼,回車,出現(xiàn)Dindows〉,這時需要輸入修復命令Fixboot,后面的參數(shù)為啟動扇區(qū)要寫入的磁盤盤符,這里填入C:,回車。修復完成,鍵入Exit退出。重啟后就會看到久違的雙重啟動菜單了。并且,這樣修復后基本不產生垃圾文件。
二、巧修WindowsXP 雙啟動菜單
在Windows98下全新安裝WindowsXP,會自動生成雙啟動菜單,相當方便。WindowsXP是極其穩(wěn)定的操作系統(tǒng),但因為雙啟動菜單的文件一般都在C盤根目錄下,很易受損。雖然你可以備份與雙啟動有關的文件,還可以使用Ghost把C盤整個備份下來,或制作緊急修復軟盤以便受損時恢復,但如果使用者粗心大意沒做備份,又沒有緊急修復軟盤那怎么辦?難道要重裝WindowsXP?還有幾十個大小軟件?!其實我們還有最后一招:恢復控制臺。
開始時和重裝一樣,要選擇全新安裝,等安裝文件復制好,電腦重新啟動,選擇進入恢復控制臺,控制臺會提示你要登錄到哪個WindowsXP安裝,一般就選默認的“1”,鍵入系統(tǒng)管理員密碼,你就進入了控制臺的Windows目錄下,鍵入“BOOTCFG/ADD”,控制臺會掃描Windows安裝,幾秒鐘后掃描完成,提示選擇要添加的安裝,選“1”,接著提示輸入加載識別符,可輸入“MicrosoftWindowsXPProfessional”,提示輸入OS加載選項,鍵入fastdetect,回車,鍵入“EXIT”,重新啟動電腦,你可以看到熟悉的雙啟動菜單又回來了。進入系統(tǒng)后,把所有分區(qū)內帶“$”的文件及文件夾全刪掉。
三、恢復WinMe\XP雙系統(tǒng)引導菜單
同時體驗兩個Windows操作系統(tǒng)的魅力,采用Windows Me與Windows XP雙重引導,是很多用戶的選擇。但是,由于種種原因,很多時候你可能要重裝Windows Me。而這一重裝不要緊,之后你會發(fā)現(xiàn)用于雙引導的啟動選擇菜單不見了(這種情況見于在DOS下重裝Windows 9x、特別是格式化C盤后的重裝)!那么,Windows XP到底上哪兒去了呢?
和平共處有順序
一般而言,在安裝雙系統(tǒng)的時候,我們是先安裝Windows Me,然后在另一個分區(qū)安裝Windows XP。
安裝了Windows Me之后,C盤引導區(qū)儲存的是Windows Me的引導信息,開機后系統(tǒng)通過加載系統(tǒng)文件Io.sys和Command.com來引導Windows Me。
安裝Windows XP之后,C盤引導區(qū)被Windows XP的引導信息所覆蓋,用來啟動Windows Me的引導信息被移到引導區(qū)以外,儲存在一個名為Bootsect.dos的文件中。
實現(xiàn)雙引導后,系統(tǒng)通過加載Windows XP的系統(tǒng)文件Ntldr來讀取Boot.ini,查找其他操作系統(tǒng),并顯示啟動選擇菜單,讓用戶確定啟動哪個系統(tǒng):如果選擇啟動Windows Me,則通過Bootsect.dos來加載Io.sys和Command.com系統(tǒng)文件來引導Windows Me;如果選擇啟動Windows XP,則直接加載Ntldr、通過Nntdetect.com系統(tǒng)文件來引導Windows XP。
不同分區(qū)是前提
而一旦再次安裝Windows Me時,C盤的引導區(qū)再次變成Windows Me的引導信息,即使Ntldr和Boot.ini兩個文件仍存在,開機時系統(tǒng)也不再加載它們,因此不會出現(xiàn)啟動選擇菜單;如果格式化了C盤,這兩個文件將不復存在,就更不會出現(xiàn)啟動選擇菜單了。
其實,大多數(shù)用戶的Windows Me與Windows XP并沒有安裝在同一個分區(qū),雖經格式化C盤、重裝Windows Me,變化的僅僅是C盤的引導區(qū)、選擇引導不同系統(tǒng)的系統(tǒng)文件,以及C盤上的Windows Me的安裝文件和設置信息。也就是說,保存在其他分區(qū)中的Windows XP安裝文件、設置信息并沒有被破壞,因此,無需費時費力地重新安裝和設置Windows XP,只要恢復一下C盤的引導區(qū)和選擇引導系統(tǒng)的系統(tǒng)文件,就可以快速恢復Windows Me與Windows XP的雙重引導,找回原來的Windows XP!
撥開迷霧見真諦
恢復Windows Me和Windows XP雙重引導的方法是:
1、啟動Windows Me后,執(zhí)行Windows XP的安裝程序。
2、按照正常的安裝過程,在安裝第一步“安裝選項”中選擇“全新安裝(高級)”。
3、輸入安裝密碼,跳過“升級驅動器”(不選“升級為NTFS文件系統(tǒng)”)和“下載更新的安裝程序文件”兩步。
4、系統(tǒng)開始復制安裝文件,等綠色的復制進度條到頭后,出現(xiàn)“重新啟動計算機”的紅色進度條,此時,迅速按下“Esc”鍵,禁止重新啟動(成功禁止重新啟動則直接進入第7步)。
5、如果沒有及時按下“Esc”鍵而導致系統(tǒng)重新啟動,將會出現(xiàn)啟動選擇菜單,其中包括三個啟動選項(格式化C盤后重裝,則只出現(xiàn)后兩項):
Microsoft Windows XP Professional
Microsoft Windows Millennium Edition
Microsoft Windows XP Professional安裝程序
6、按小鍵盤區(qū)的方向鍵,在5秒鐘內選擇“Microsoft Windows Millennium Edition”啟動Windows Me。
7、進入C盤即可看到,根目錄上已經出現(xiàn)了實現(xiàn)雙引導啟動需要的五個文件:“Ntldr”、“Ntdetect.com”、“Boot.ini”、“Bootfont.bin”、“Bootsect.dos”。
此外還有Windows XP的三個安裝文件“ldr”、“drvltr.~_~”、“txtse-tup.sif”和一個文件夾“win_nt.~bt”,其他分區(qū)也各有一個磁盤加速文件“DRVLTR.~_~”,直接刪除即可。
8、修改Boot.ini文件。在[Boot Loader]段中:將“Default=C:\WIN_NT.~BT\BOOTSECT.DAT”一行改為“Default=C:\”,如果不從啟動選擇菜單中進行選擇,默認從C盤引導啟動Windows Me;或改為“Default=multi(0)disk(0)rdisk(0)partition(2)\WINDOWS”,使系統(tǒng)默認從D盤引導啟動Windows XP(如果Windows XP安裝在E盤,將“partition(2)”中的“2”改為“3”、以此類推)。
同時,還可在[Boot Loader]段中設定啟動選擇菜單維持的時間(以秒為單位),將“Timeout=5”中的“5”改為你希望的時間即可。
在[Operating Systems]段中,刪除“C:\WIN_NT.~BT\BOOTSECT.DAT="Microsoft Windows XP Professional安裝程序"”一行,即可將Windows XP的安裝選項從啟動選擇菜單中屏蔽掉。若是格式化C盤后重裝Windows Me,還需加入“multi(0)disk(0)rdisk(0)partition(2)\WINDOWS="Microsoft Windows XP Professional"/fastdetect”一行,使系統(tǒng)以快速啟動的方式從D盤引導Windows XP。同時,還可以在[Operating Systems]段中修改啟動選擇菜單顯示的文字,比如:將“Microsoft Windows XP Professional”改為“Windows XP中文版”、“Microsoft Windows Millennium Edition”改為“Windows Me千禧版”,之后,選擇引導菜單上顯示的就是“Windows XP中文版”和“Windows Me千禧版”了。
9、重新啟動就恢復雙重引導了,并且,Windows XP的全部設置百分之百保持原來的狀態(tài),與重裝Windows Me前沒有絲毫改變。
四、修復雙系統(tǒng)啟動菜單
如果安裝了了雙操作系統(tǒng)的朋友就會知道,一般雙系統(tǒng)都會是98/me加上2000/xp這樣類型的操作系統(tǒng),在安裝操作系統(tǒng)的時候xp/2000會自動建立起一個雙重系統(tǒng)啟動菜單,雙重系統(tǒng)的啟動是因為在c盤的根目錄下面含有這樣幾個文件:win.ini boot.ini bootfont.bin ntdetect.com ntldr io.sys msdos.sys 后面這兩個是要在文件夾選項里面更改(隱藏受保護的系統(tǒng)文件)才能看到的。最好在其中的一個系統(tǒng)壞了以后先備份這幾個文件,如果沒有備份就先把c盤格式化了,并且安裝好了98/me的話是不是感到沒有辦法了恢復了呢?這里介紹一種簡單的方法:
先把xp/或者2000的安裝光盤放入光驅,并且執(zhí)行setup安裝xp/2000,選擇全新安裝。安裝程序就會繼續(xù)安裝,等待重啟以后不要繼續(xù)安裝了,直接進入me/98,觀察c盤根目錄,多了幾個文件夾,還有一些看不懂的文件。但是更改了文件夾選項里面的(隱藏受保護的系統(tǒng)文件)以后發(fā)現(xiàn)win.ini boot.ini bootfont.bin ntdetect.com ntldr io.sys msdos.sys都恢復了,那么你可以直接刪除其他你看不懂的文件名很奇怪的文件夾了,因為那是為windows xp/2000安裝準備的安裝文件,然后打開并這樣編輯boot.ini
[boot loader]
timeout=10
default=multi(0)disk(0)rdisk(0)partition(2)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(2)\WINDOWS="①: Windows XP/2000 " /fastdetect
C:\=②: Windows ME/98
然后重新系統(tǒng)啟動就可以了 發(fā)現(xiàn)雙啟動菜單已經恢復了。
五、雙操作系統(tǒng)共存常見問題解答
雙系統(tǒng)的安裝順序
問:我打算在一臺電腦中安裝多系統(tǒng)(Windows 9x/XP),請問在安裝的先后順序上有什么講究么?應該注意哪些地方?
答:一般來說,安裝順序是先低級版本到高級版本的,也就是說首先安裝Windows9x,然后在Windows9x系統(tǒng)下安裝WindowsXP,這樣做的好處是系統(tǒng)可以自動生成開機選擇畫面。
要注意的有以下幾點:
1、要把每個系統(tǒng)安裝在不同的分區(qū)中。最好的安排是:把Windows 9x安裝在C盤上,Windows XP安裝在D盤上。
2、針對不同的系統(tǒng)要選擇不同的系統(tǒng)文件格式。對于Windows9x,要選擇FAT16或FAT32的;而對于Windows XP,最好使用NTFS格式,這樣系統(tǒng)潛力會發(fā)揮的更好。
3、在Windows9x上安裝Windows XP時要選擇“全新安裝”,不要選擇“升級安裝”。
高版本如何安裝低版本
問:我的系統(tǒng)是Windows XP,現(xiàn)在我想再安裝一個Windows 98,請問如何在保留Windows XP的情況下安裝Windows 98,做個雙系統(tǒng)?
答:因為Windows XP下不能直接安裝Windows 98,所以必須首先用Windows 98啟動盤啟動電腦(當然前提是在CMOS中設置先從A盤啟動),然后把Windows98安裝到WindowsXP以外的分區(qū)中。重啟系統(tǒng)后,你會發(fā)現(xiàn)并沒有雙啟動菜單,系統(tǒng)直接進入了Windows 98。不要緊,按照下一個問題的解答恢復即可。恢復完后把硬盤各分區(qū)中以“”字符打頭并以“”結尾的文件刪除就可以了。
恢復選擇菜單
問:我安裝的是Windows 98加Windows 2000操作系統(tǒng),由于誤操作把boot.ini文件刪除了,現(xiàn)在啟動電腦時就會出現(xiàn)“boot.ini非法”提示,也沒有選擇菜單了,而是直接進入了Windows 2000,請問該如何恢復?
答:首先在BIOS中將啟動順序調整為CD-ROM引導,然后將Windows 2000安裝盤放入光驅。等自動加載完安裝程序后,系統(tǒng)會問你是重新安裝還是修復,不用管它,直接退出。最后到CMOS中把啟動順序再改為硬盤啟動,這樣再次開機后就會出現(xiàn)選擇菜單了。
刪除其中一個系統(tǒng)
問:請問在雙系統(tǒng)中(Windows9x和Windows XP),如何在不損害一個系統(tǒng)的情況下刪除另外一個系統(tǒng)?
答:如果想刪除Windows9x的話,可以在Windows XP中右鍵單擊“我的電腦”,選擇“屬性→高級”,點擊“啟動和故障恢復”中的“設置”按鈕,然后把啟動時間改為“0”,這樣在啟動時就會直接進入Windows XP,而不會在出現(xiàn)選擇菜單了。最后把Windows 9x的Windows、Program Files目錄和引導文件(包括io.sys、msdos.sys、command.com、autoexec.bat和config.sys)刪除即可。
如果想刪除Windows XP,首先在Windows 9x環(huán)境下把Windows XP所在的目錄全部刪除,然后用一張Windows 9x的啟動盤(根據(jù)操作系統(tǒng)所定)啟動,在“A:”下輸入“SYS C:”,給Windows9x所在的C盤重新傳系統(tǒng)即可。
如何訪問NTFS分區(qū)
問:我的電腦是Windows 98、Windows 2000的雙系統(tǒng),Windows 2000所在的分區(qū)使用了NTFS文件格式,這樣我在Windows 98下就不能訪問它們了,請問如何在不轉化為FAT格式的情況下訪問它們呢?
答:目前沒有太好的辦法,只能使用軟件NTFS for Windows 98,它是專為Windows 9x系統(tǒng)訪問NTFS分區(qū)而設計的,使用它可以在Windows 9x環(huán)境下對NTFS分區(qū)進行讀寫等操作.