程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Struts2文件上傳(二) 深入FileUploadInterceptor

Struts2文件上傳(二) 深入FileUploadInterceptor

編輯:關於JAVA

Struts2框架本身沒有文件上傳的功能模塊,而是利用現在流行的幾個文件上傳開源框架,如Common -FileUpload和COS等。 Struts2利用攔截器將這些文件上傳的框架巧妙的集成進來,不能不被稱為一個 優秀的拿來主義者。由於攔截器的使用,我們使用Struts2實現文件上傳變的非常容易,似乎什麼也沒發生,文件已經上傳到服務器了,但如果僅僅是使用這個功能,可能永遠不知道Struts2為你做了多少事情 。最近有點閒,分析了下下Struts2源碼,才弄清楚其中的真相,筆記一下,以免遺忘。

Struts2利用request解析器來集成其他的文件上傳框架,Struts2提供了默認的request解析器 JakartaMultiPartRequest,在default.properties的struts.multipart.parser參數就是配置request解 析器,默認為jakarta也就是JakartaMultiPartRequest。當然,你也可以設置成cos,不過Struts2 沒有 提供適配cos的request解析器,你得自己實現,然後配置到自己的應用。JakartaMultiPartRequest也就 是利用 Common-FileUpload來對request進行解析,然後保存解析結果。具體工作就是利用Common- FileUpload的 ServletFileUpload對request進行解析,得到所有的FileItem的list,然後對這個list進 行分析。如果是文件上傳表單,則以表單的name屬性分組,以表單name屬性為key,對應的FileItem列表 為Value保存到一個Map中。JakartaMultiPartRequest的工作已經完成,當然,這個Map中保存的所有的 FileItem,框架已經將文件保存到一個臨時目錄裡了,這個臨時目錄你也可以配置,參數為struts.multipart.saveDir,還要配置一個文件上傳總大小,參數為 struts.multipart.maxSize。

接著就是FileUploadInterceptor的工作了,他的工作也非常簡單。首先進行驗證,如文件上傳 大小限制,上傳類型限制驗證等。然後以表單名來構造三個參數,例如:你的文件上傳表單name為 upload,則這三個參數為:upload,uploadContentType,uploadFileName。然後保存到ActionContext的 PARAMETERS 中,當然如果表單很多,而且表單名又不同,他就會產生不同表單名對應的參數。最後系統 的ParametersInterceptor攔截器會將 ActionContext的getParameters()得到的各個參數映射賦值給 Action的各個屬性,這就是為什麼我們在開發文件上傳的時候一定要在Action中提供與表單名相同的 File對象(如果一個表單名又多個上傳文件,這是可以是File數組或是File的List),文件名 +ContentType,和文件名+FileName 這三種參數。

框架為我們所做的就是這些了,剩下的就是文 件拷貝了。現在我們來注意下Action的這幾個參數,其中File對象(當然也可能是數組或List),這時他 們已經指向系統臨時目錄裡的某個文件,或是系統的內存裡的數據了。在我們傳輸數據時,實際上是從 這個臨時文件或內存將數據庫拷貝到上傳目錄裡去的,當執行完Action之後,FileUploadInterceptor會 將臨時目錄裡所有臨時文件刪除,這也是為什麼上傳文件完成後會有一些日志顯示說刪除了一些臨時文 件的原因。

現在實現一個簡單的文件上傳,首先熟悉下幾個參數配置:

1.struts.multipart.parser  配置request解析器,Struts2默認為jakarta 也就是 JakartaMultiPartRequest,我們也 可以自己開發自己的解析器。

2.struts.multipart.saveDir   上傳文件的臨時保存目錄,我們知道Common-FileUpload需要提供一個臨時目錄的。如果沒有設置, 則是 ServletContext.getAttribute("javax.servlet.context.tempdir")對應的目錄,對應於 Common- FileUpoad中的repository參數。

3.struts.multipart.maxSize 這個是配置文件上傳總大小,單 位為B,默認大小為2097152b,對應於Common-FileUpload中的sizeMax參數。

在配置 FileUploadInterceptor時候也有幾個參數:

1.maximumSize  這是設置允許上傳的單個文件的 大小,如果某個文件大小大於這個大小,則會產生一個錯誤保存到Action中,錯誤的i18n的key為 struts.messages.error.file.too.large

2.allowedTypesSet 這是設置允許上傳文件的類型,多 個類型以逗號“,”隔開,如果某個文件的類型沒在這個設置之類,則會產生一個錯誤保存 到Action中,錯誤的i18n的的key為 struts.messages.error.content.type.not.allowed

3.allowedExtensionsSet這是設置允許上傳 文件的後綴,多個類型以逗號“,”隔開,如果某個文件的後綴沒在這個設置之類,則會產 生一個錯誤保存到Action中,錯誤的i18n的的key為 struts.messages.error.file.extension.not.allowed

struts.xml配置示例:

Xml代碼

<struts>
//配置文件保存的臨時目錄
<constant  name="struts.multipart.saveDir" value="C:\Documents and Settings\bond\My  Documents\temp"></constant>

//配置上傳總大小
<constant  name="struts.multipart.maxSize" value="1024102400"></constant>

<package name="strutsDemo" extends="struts-default">

<action  name="Upload" method="upload" class="com.bond.action.LoginAction">
//文件上傳的保 存目錄
<param name="savePath">/upload</param>
<result  name="success">/success.jsp</result>
<result  name="error">/failure.jsp</result>
<interceptor-ref  name="fileUpload">
//單個文件允許的大小
<param  name="maxinumSize">10240000000</param>
//允許上傳的文件類型,可以到% Tomcat_home%/conf下的web.xml文件中找到所有文件類型的類型名
<param  name="allowedTypesSet">application/zip,application/pdf,image/gif</param>
</interceptor-ref>
<interceptor-ref  name="defaultStack"></interceptor-ref>
</action>
</package>
</struts>

這裡我們配置了fileUpload攔截器,我們還 必須吧dufaultStack加上,由於defaultStack中已經包含了fileUpload攔截器,所以fileUpload攔截器 會執行倆遍,所以我們會在日志信息中看到倆次清除臨時文件的記錄。

UploadAction:

Java代碼

public class UploadAction extends ActionSupport {
// 必須的參數,參數名與表單名相同,如果一個表單名對應多個上傳文件,
//則必須為數組或 List
private File[] upload;
//必須的參數,格式:表單名+ContentType,表示上傳文 件類型
private String[] uploadContentType;
//必須的參數,格式:表單名+FileName ,表示上傳的文件名
private String[] uploadFileName;
//文件保存目錄
private  String savePath;

public LoginAction() {
}

public String  upload() throws Exception {
for (int i=0;i<getUpload().length;i++) {
FileInputStream in = new FileInputStream(getUpload()[i]);
FileOutputStream out  = new FileOutputStream(getSavePath()+"\\"+getUploadFileName()[i]);
//將數據拷貝到 上傳目錄,這裡沒有必要使用緩沖流,因為IOUtils工具類已經使用了緩存
IOUtils.copy(in,  out);
}
return SUCCESS;
}
。。。。。。get/set方法。。。。

頁面表單示例:

Html代碼

<!-- method一定要為post, enctype一定要為 multipart/form-data,表單名一定要和Action中的參數名相同-->
<s:form method="post" id="loginForm" action="Upload"
enctype="multipart/form- data">
<table style="border: 1px solid;" align="center">
<thead>
<tr>
<td style="text-align: center" colspan="2">文 件上傳</td>
</tr>
</thead>
<tbody>
<tr>
<td>用戶名:</td>
<td><input type="text"  name="username"></input></td>
</tr>
<tr>
<td>密碼:</td>
<td><input type="text"  name="password"></input></td>
</tr>
<tr>
<td  colspan="2"><input type="file" name="upload" /></td>
</tr>
<tr>
<td colspan="2"><input type="file"  name="upload" /></td>
</tr>
<tr>
<td  colspan="2"><input type="file" name="upload" /></td>
</tr>
<tr>
<td><input type="button" value="Upload"  id="upload" /></td>
<td><input type="button" value="Cancel"  id="cancelUpload" /></td>
</tr>
</tbody>
</table>

這樣,一個簡單的文件上傳就實現了,但是感覺文件上傳無聲無息, 特別上傳大文件,等了很長時間才知道有沒有上傳成功,要是有上傳進度條能及時顯示上傳進度,這樣 的文件上傳的功能才能算完善了,上傳進度條的功能下篇再寫。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved