Java Web開發(fā)人員可以使用Apache文件上傳組件來接收瀏覽器上傳的文件,該組件由多個類共同組成,但是,對于使用該組件來編寫文件上傳功能的Java Web開發(fā)人員來說,只需要了解和使用其中的三個類:DiskFileUpload、FileItem和FileUploadException。這三個類全部位于org.apache.commons.fileupload包中。
查看API文檔
在準(zhǔn)備實驗環(huán)境時獲得的commons-fileupload-1.0.zip文件的解壓縮目錄中可以看到一個docs的子目錄,其中包含了Apache文件上傳組件中的各個API類的幫助文檔,從這個文檔中可以了解到各個API類的使用幫助信息。打開文件上傳組件API幫助文檔中的index.html頁面,在左側(cè)分欄窗口頁面中列出了文件上傳組件中的各個API類的名稱,在右側(cè)分欄窗口頁面的底部列出了一段示例代碼,如圖1.2所示。
圖1.2
讀者不需要逐個去閱讀圖1.2中列出的各個API類的幫助文檔,而應(yīng)該以圖1.2中的示例代碼為線索,以其中所使用到的類為入口點,按圖索驥地進(jìn)行閱讀,對于示例代碼中調(diào)用到的各個API類的方法則應(yīng)重點掌握。
1. DiskFileUpload類
DiskFileUpload類是Apache文件上傳組件的核心類,應(yīng)用程序開發(fā)人員通過這個類來與Apache文件上傳組件進(jìn)行交互。但現(xiàn)在Apache建議使用ServletFileUpload類,兩個類的方法類似。下面介紹DiskFileUpload類中的幾個常用的重要方法。
1.1.setSizeMax方法
setSizeMax方法用于設(shè)置請求消息實體內(nèi)容的最大允許大小,以防止客戶端故意通過上傳特大的文件來塞滿服務(wù)器端的存儲空間,單位為字節(jié)。其完整語法定義如下:
public void setSizeMax(long sizeMax)
如果請求消息中的實體內(nèi)容的大小超過了setSizeMax方法的設(shè)置值,該方法將會拋出FileUploadException異常。
1.2.setSizeThreshold方法
Apache文件上傳組件在解析和處理上傳數(shù)據(jù)中的每個字段內(nèi)容時,需要臨時保存解析出的數(shù)據(jù)。因為Java虛擬機(jī)默認(rèn)可以使用的內(nèi)存空間是有限的(筆者測試不大于100M),超出限制時將會發(fā)生“java.lang.OutOfMemoryError”錯誤,如果上傳的文件很大,例如上傳800M的文件,在內(nèi)存中將無法保存該文件內(nèi)容,Apache文件上傳組件將用臨時文件來保存這些數(shù)據(jù);但如果上傳的文件很小,例如上傳600個字節(jié)的文件,顯然將其直接保存在內(nèi)存中更加有效。setSizeThreshold方法用于設(shè)置是否使用臨時文件保存解析出的數(shù)據(jù)的那個臨界值,該方法傳入的參數(shù)的單位是字節(jié)。其完整語法定義如下:
public void setSizeThreshold(int sizeThreshold)
1.3. setRepositoryPath方法
setRepositoryPath方法用于設(shè)置setSizeThreshold方法中提到的臨時文件的存放目錄,這里要求使用絕對路徑。其完整語法定義如下:
public void setRepositoryPath(String repositoryPath)
如果不設(shè)置存放路徑,那么臨時文件將被儲存在"java.io.tmpdir"這個JVM環(huán)境屬性所指定的目錄中,tomcat 5.5.9將這個屬性設(shè)置為了“<tomcat安裝目錄>/temp/”目錄。
1.4. parseRequest方法
parseRequest 方法是DiskFileUpload類的重要方法,它是對HTTP請求消息進(jìn)行解析的入口方法,如果請求消息中的實體內(nèi)容的類型不是“multipart/form-data”,該方法將拋出FileUploadException異常。parseRequest 方法解析出FORM表單中的每個字段的數(shù)據(jù),并將它們分別包裝成獨立的FileItem對象,然后將這些FileItem對象加入進(jìn)一個List類型的集合對象中返回。parseRequest 方法的完整語法定義如下:
public List parseRequest(HttpServletRequest req)
parseRequest 方法還有一個重載方法,該方法集中處理上述所有方法的功能,其完整語法定義如下:
parseRequest(HttpServletRequest req,int sizeThreshold,long sizeMax,
String path)
這兩個parseRequest方法都會拋出FileUploadException異常。
1.5. isMultipartContent方法
isMultipartContent方法方法用于判斷請求消息中的內(nèi)容是否是“multipart/form-data”類型,是則返回true,否則返回false。isMultipartContent方法是一個靜態(tài)方法,不用創(chuàng)建DiskFileUpload類的實例對象即可被調(diào)用,其完整語法定義如下:
public static final boolean isMultipartContent(HttpServletRequest req)
1.6. setHeaderEncoding方法
由于瀏覽器在提交FORM表單時,會將普通表單中填寫的文本內(nèi)容傳遞給服務(wù)器,對于文件上傳字段,除了傳遞原始的文件內(nèi)容外,還要傳遞其文件路徑名等信息,如后面的圖1.3所示。不管FORM表單采用的是“application/x-www-form-urlencoded”編碼,還是“multipart/form-data”編碼,它們僅僅是將各個FORM表單字段元素內(nèi)容組織到一起的一種格式,而這些內(nèi)容又是由某種字符集編碼來表示的。關(guān)于瀏覽器采用何種字符集來編碼FORM表單字段中的內(nèi)容,請參看筆者編著的《深入體驗java Web開發(fā)內(nèi)幕——核心基礎(chǔ)》一書中的第6.9.2的講解,“multipart/form-data”類型的表單為表單字段內(nèi)容選擇字符集編碼的原理和方式與“application/x-www-form-urlencoded”類型的表單是相同的。FORM表單中填寫的文本內(nèi)容和文件上傳字段中的文件路徑名在內(nèi)存中就是它們的某種字符集編碼的字節(jié)數(shù)組形式,Apache文件上傳組件在讀取這些內(nèi)容時,必須知道它們所采用的字符集編碼,才能將它們轉(zhuǎn)換成正確的字符文本返回。
對于瀏覽器上傳給WEB服務(wù)器的各個表單字段的描述頭內(nèi)容,Apache文件上傳組件都需要將它們轉(zhuǎn)換成字符串形式返回,setHeaderEncoding 方法用于設(shè)置轉(zhuǎn)換時所使用的字符集編碼,其原理與筆者編著的《深入體驗java Web開發(fā)內(nèi)幕——核心基礎(chǔ)》一書中的第6.9.4節(jié)講解的ServletRequest.setCharacterEncoding方法相同。setHeaderEncoding 方法的完整語法定義如下:
public void setHeaderEncoding(String encoding)
其中,encoding參數(shù)用于指定將各個表單字段的描述頭內(nèi)容轉(zhuǎn)換成字符串時所使用的字符集編碼。
注意:如果讀者在使用Apache文件上傳組件時遇到了中文字符的亂碼問題,一般都是沒有正確調(diào)用setHeaderEncoding方法的原因。
2. FileItem類
FileItem類用來封裝單個表單字段元素的數(shù)據(jù),一個表單字段元素對應(yīng)一個FileItem對象,通過調(diào)用FileItem對象的方法可以獲得相關(guān)表單字段元素的數(shù)據(jù)。FileItem是一個接口,在應(yīng)用程序中使用的實際上是該接口一個實現(xiàn)類,該實現(xiàn)類的名稱并不重要,程序可以采用FileItem接口類型來對它進(jìn)行引用和訪問,為了便于講解,這里將FileItem實現(xiàn)類稱之為FileItem類。FileItem類還實現(xiàn)了Serializable接口,以支持序列化操作。
對于“multipart/form-data”類型的FORM表單,瀏覽器上傳的實體內(nèi)容中的每個表單字段元素的數(shù)據(jù)之間用字段分隔界線進(jìn)行分割,兩個分隔界線間的內(nèi)容稱為一個分區(qū),每個分區(qū)中的內(nèi)容可以被看作兩部分,一部分是對表單字段元素進(jìn)行描述的描述頭,另外一部是表單字段元素的主體內(nèi)容,如圖1.3所示。
圖 1.3
主體部分有兩種可能性,要么是用戶填寫的表單內(nèi)容,要么是文件內(nèi)容。FileItem類對象實際上就是對圖1.3中的一個分區(qū)的數(shù)據(jù)進(jìn)行封裝的對象,它內(nèi)部用了兩個成員變量來分別存儲描述頭和主體內(nèi)容,其中保存主體內(nèi)容的變量是一個輸出流類型的對象。當(dāng)主體內(nèi)容的大小小于DiskFileUpload.setSizeThreshold方法設(shè)置的臨界值大小時,這個流對象關(guān)聯(lián)到一片內(nèi)存,主體內(nèi)容將會被保存在內(nèi)存中。當(dāng)主體內(nèi)容的數(shù)據(jù)超過DiskFileUpload.setSizeThreshold方法設(shè)置的臨界值大小時,這個流對象關(guān)聯(lián)到硬盤上的一個臨時文件,主體內(nèi)容將被保存到該臨時文件中。臨時文件的存儲目錄由DiskFileUpload.setRepositoryPath方法設(shè)置,臨時文件名的格式為“upload_00000005(八位或八位以上的數(shù)字).tmp”這種形式,FileItem類內(nèi)部提供了維護(hù)臨時文件名中的數(shù)值不重復(fù)的機(jī)制,以保證了臨時文件名的唯一性。當(dāng)應(yīng)用程序?qū)⒅黧w內(nèi)容保存到一個指定的文件中時,或者在FileItem對象被垃圾回收器回收時,或者Java虛擬機(jī)結(jié)束時,Apache文件上傳組件都會嘗試刪除臨時文件,以盡量保證臨時文件能被及時清除。
下面介紹FileItem類中的幾個常用的方法:
2.1. isFormField方法
isFormField方法用于判斷FileItem類對象封裝的數(shù)據(jù)是否屬于一個普通表單字段,還是屬于一個文件表單字段,如果是普通表單字段則返回true,否則返回false。該方法的完整語法定義如下:
public boolean isFormField()
2.2. getName方法
getName方法用于獲得文件上傳字段中的文件名,對于圖1.3中的第三個分區(qū)所示的描述頭,getName方法返回的結(jié)果為字符串“C:"bg.gif”。如果FileItem類對象對應(yīng)的是普通表單字段,getName方法將返回null。即使用戶沒有通過網(wǎng)頁表單中的文件字段傳遞任何文件,但只要設(shè)置了文件表單字段的name屬性,瀏覽器也會將文件字段的信息傳遞給服務(wù)器,只是文件名和文件內(nèi)容部分都為空,但這個表單字段仍然對應(yīng)一個FileItem對象,此時,getName方法返回結(jié)果為空字符串"",讀者在調(diào)用Apache文件上傳組件時要注意考慮這個情況。getName方法的完整語法定義如下:
public String getName()
注意:如果用戶使用Windows系統(tǒng)上傳文件,瀏覽器將傳遞該文件的完整路徑,如果用戶使用Linux或者Unix系統(tǒng)上傳文件,瀏覽器將只傳遞該文件的名稱部分。
2.3.getFieldName方法
getFieldName方法用于返回表單字段元素的name屬性值,也就是返回圖1.3中的各個描述頭部分中的name屬性值,例如“name=p1”中的“p1”。getFieldName方法的完整語法定義如下:
public String getFieldName()
2.4. write方法
write方法用于將FileItem對象中保存的主體內(nèi)容保存到某個指定的文件中。如果FileItem對象中的主體內(nèi)容是保存在某個臨時文件中,該方法順利完成后,臨時文件有可能會被清除。該方法也可將普通表單字段內(nèi)容寫入到一個文件中,但它主要用途是將上傳的文件內(nèi)容保存在本地文件系統(tǒng)中。其完整語法定義如下:
public void write(File file)
2.5.getString方法
getString方法用于將FileItem對象中保存的主體內(nèi)容作為一個字符串返回,它有兩個重載的定義形式:
public java.lang.String getString()
public java.lang.String getString(java.lang.String encoding)
throws java.io.UnsupportedEncodingException
前者使用缺省的字符集編碼將主體內(nèi)容轉(zhuǎn)換成字符串,后者使用參數(shù)指定的字符集編碼將主體內(nèi)容轉(zhuǎn)換成字符串。如果在讀取普通表單字段元素的內(nèi)容時出現(xiàn)了中文亂碼現(xiàn)象,請調(diào)用第二個getString方法,并為之傳遞正確的字符集編碼名稱。
2.6. getContentType方法
getContentType 方法用于獲得上傳文件的類型,對于圖1.3中的第三個分區(qū)所示的描述頭,getContentType方法返回的結(jié)果為字符串“image/gif”,即“Content-Type”字段的值部分。如果FileItem類對象對應(yīng)的是普通表單字段,該方法將返回null。getContentType 方法的完整語法定義如下:
public String getContentType()
2.7. isInMemory方法
isInMemory方法用來判斷FileItem類對象封裝的主體內(nèi)容是存儲在內(nèi)存中,還是存儲在臨時文件中,如果存儲在內(nèi)存中則返回true,否則返回false。其完整語法定義如下:
public boolean isInMemory()
2.8. delete方法
delete方法用來清空FileItem類對象中存放的主體內(nèi)容,如果主體內(nèi)容被保存在臨時文件中,delete方法將刪除該臨時文件。盡管Apache組件使用了多種方式來盡量及時清理臨時文件,但系統(tǒng)出現(xiàn)異常時,仍有可能造成有的臨時文件被永久保存在了硬盤中。在有些情況下,可以調(diào)用這個方法來及時刪除臨時文件。其完整語法定義如下:
public void delete()
3. FileUploadException類
在文件上傳過程中,可能發(fā)生各種各樣的異常,例如網(wǎng)絡(luò)中斷、數(shù)據(jù)丟失等等。為了對不同異常進(jìn)行合適的處理,Apache文件上傳組件還開發(fā)了四個異常類,其中FileUploadException是其他異常類的父類,其他幾個類只是被間接調(diào)用的底層類,對于Apache組件調(diào)用人員來說,只需對FileUploadException異常類進(jìn)行捕獲和處理即可。
4. ServletRequestContext
ServletRequestContext類提供訪問request的方法。實現(xiàn)RequestContext接口。
posted @
2009-12-03 13:46 FOG 閱讀(298) |
評論 (0) |
編輯 收藏
prototype.js是一個很強(qiáng)大的Javascript函數(shù)庫,它可以讓你很輕松的使用一些特效,實現(xiàn)AJAX的功能.雖然prototype.js是為了Ruby On Rails開發(fā)的,它的純Javascript的性質(zhì)也使得它很容易用在其他的網(wǎng)絡(luò)程序中.可惜的是,Prototype.js還沒有強(qiáng)大的文檔解釋,盡管它的代碼非常有條理,但是也給初學(xué)者造成了一定的麻煩.作者在README里說:
Prototype is embarrassingly lacking in documentation. (The source code should be fairly easy to comprehend; I’m committed to using a clean style with meaningful identifiers. But I know that only goes so far.)
基本用法:以Element Class為例,prototype給每個主要的分類都分成了一個Class,使用起來很方便,要產(chǎn)生特定的效果的話只要用new Class.function(<argument>)就可以了.比如:
<DIV id="div1"><a href="#" onclick="new Element.toggle(''div2'')">Click Me</a></DIV>
<DIV id="div2">Hello!</DIV>
當(dāng)點擊Click Me的時候,div2就會交替隱藏或顯示.注意,你可以給toggle加上無限個parameter,比如Element.toggle(''div2'',''div3'',''div4'')...
下面是每個重要的類和函數(shù)的解釋:
prototype 1.2.0 的函數(shù)簡介
函數(shù)名 |
解釋 |
舉例 |
Element.toggle |
交替隱藏或顯示 |
"Element.toggle(''div1'',''div2'') |
Element.hide |
隱藏 |
"Element.hide(''div1'',''div2'') |
Element.show |
顯示 |
"Element.show(''div1'',''div2'') |
Element.remove |
刪除 |
"Element.remove(''div1'',''div2'') |
Element.getHeight |
取得高度 |
"Element.getHeight(''div1'') |
Toggle.display |
和Element.toggle相同 |
"Toggle.display(''div1'',''div2'') |
Insertion.Before |
在DIV前插入文字 |
"Insertion.Before(''div1'',''my content'') |
Insertion.After |
在DIV后插入文字 |
"Insertion.After(''div1'',''my content'') |
Insertion.Top |
在DIV里最前插入文字 |
"Insertion.Top(''div1'',''this is a text'') |
Insertion.Bottom |
在DIV里最后插入文字 |
"Insertion.Bottom(''div1'',''this is a text'') |
PeriodicalExecuter |
以給定頻率調(diào)用一段JavaScript |
"PeridicalExecutor(test, 1)"這里test是Javascript的函數(shù),1是頻率(1秒). |
$ |
取得一個DIV, 相當(dāng)于getElementById() |
$(''div1'') |
Field.clear |
清空一個輸入框 |
"Field.clear(''textfield1'') |
Field.focus |
把 焦點集中在輸入框上 |
"Field.focus(''select1'') |
Field.present |
判斷內(nèi)容是否為空 |
"alert(Field.present(''textfield1''))" |
Field.select |
選擇輸入框的內(nèi)容 |
"Field.select(''textfield1'')" |
Field.activate |
把 焦點集中在輸入框上并選擇輸入框的內(nèi)容 |
"Field.activate(''textfield1'')" |
Form.serialize |
把表格內(nèi)容轉(zhuǎn)化成string |
|
Form.getElements |
取得表格內(nèi)容為數(shù)組形式 |
|
Form.disable |
disable表格所有內(nèi)容 |
Form.disable(''form1'') (這個好象不work) |
Form.focusFirstElement |
把焦點集中在表格第一個元素上 |
Form.focusFirstElement(''form1'') |
Form.reset |
Reset表格 |
Form.reset(''form1'') |
Form.Element.getValue |
取得表格輸入框的值 |
Form.Element.getValue(''text1'') |
Form.Element.serialize |
把表格中輸入框內(nèi)容轉(zhuǎn)化成string |
Form.Element.serialize(''text1'') |
$F |
等同于Form.Element.getValue() |
$F(''text1'') |
Effect.Highlight |
高亮特效. |
Effect.Highlight(''text1'') |
Effect.Fade |
褪色特效 |
|
Effect.Scale |
放大縮小(百分比) |
Effect.Scale(''text1'', 200)
這里200 = 200%, 即兩倍
|
Effect.Squish |
消失特效.文字縮小后消失 |
Effect.Squish(''text1'') |
Effect.Puff |
消失特效.文字放大后消失 |
Effect.Puff(''text1'') |
Effect.Appear |
出現(xiàn)特效 |
|
Effect.ContentZoom |
ZOOM特效. |
|
Ajax.Request |
傳送Ajax請求給服務(wù)器 |
Ajax.Request(''http://server/s.php'') |
Ajax.Updater |
傳送Ajax請求給服務(wù)器并用答復(fù)的結(jié)果更新指定的Container |
Ajax.Updater(''text1'',''http://server/s.php'') |
Ajax的函數(shù)實際上還有一個可選參數(shù),就是options.在未指明的情況下,Ajax使用的是''POST''發(fā)送請求,而且是異步執(zhí)行,如果想要改用''GET''和同步,就可以用Ajax.Request(''http://server/s.php'',''get'','''',''a=1&b=2'')來執(zhí)行.
在Rails中Ajax的函數(shù)被封裝成Ruby的函數(shù),所以不必直接采用Ajax.Request,Ajax.Updater.但是知道它是怎么工作的也很有用.
posted @
2009-11-30 00:14 FOG 閱讀(2268) |
評論 (9) |
編輯 收藏