技術要點
本節代碼詳細說明文件上傳功能的開發流程,介紹知識點如下:
? 文件上傳頁面和顯示上傳成功頁面代碼內容。
? UploadAction類中實現上傳功能方法和上傳文件屬性介紹。
? struts.xml中UploadAction配置,以及字符編碼、文件臨時存放路徑配置。
? 上傳后所處路徑和最終上傳成功后效果展示。
演示代碼
上傳文件頁面,這里筆者定義的是多個文件上傳。
- <!---------------------文件名:upload.jsp----------------->
- <%@taglib prefix="s" uri="/struts-tags"%>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
- <title>上傳文件</title>
- </head>
- <body>
- <!-- 上傳文件表單定義 -->
- <s:form action="upload" method="post" enctype="multipart/form-data">
- <tr>
- <!-- 上傳文件標簽定義 -->
- <td>上傳文件:<s:file name="file"></s:file></td>
- </tr>
- <tr>
- <td>再次上傳文件:<s:file name="file"></s:file></td>
- </tr>
- <tr>
- <td align="left"><s:submit name="submit" value="提交"></s:submit></td>
- </tr>
- </s:form>
- </body>
- </html>
<!---------------------文件名:upload.jsp----------------->
<%@taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>上傳文件</title>
</head>
<body>
<!-- 上傳文件表單定義 -->
<s:form action="upload" method="post" enctype="multipart/form-data">
<tr>
<!-- 上傳文件標簽定義 -->
<td>上傳文件:<s:file name="file"></s:file></td>
</tr>
<tr>
<td>再次上傳文件:<s:file name="file"></s:file></td>
</tr>
<tr>
<td align="left"><s:submit name="submit" value="提交"></s:submit></td>
</tr>
</s:form>
</body>
</html>
上傳文件成功后結果頁面
- <!-------------------文件名:result.jsp ----------------->
- <%@taglib prefix="s" uri="/struts-tags"%>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
- <title>上傳結果</title>
- </head>
- <body>
- 上傳文件:
- <!-- 顯示上傳成功文件名 -->
- <s:property value="fileFileName" />
- </body>
- </html>
<!-------------------文件名:result.jsp ----------------->
<%@taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>上傳結果</title>
</head>
<body>
上傳文件:
<!-- 顯示上傳成功文件名 -->
<s:property value="fileFileName" />
</body>
</html>
UploadAction類代碼
- <!------------------文件名:UploadAction.java ------------------>
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.util.List;
-
- import org.apache.struts2.ServletActionContext;
- import com.opensymphony.xwork2.ActionSupport;
-
-
- public class UploadAction extends ActionSupport {
-
- private final static String UPLOADDIR = "/upload";
-
- private List<File> file;
-
- private List<String> fileFileName;
-
- private List<String> fileContentType;
-
- public List<File> getFile() {
- return file;
- }
-
- public void setFile(List<File> file) {
- this.file = file;
- }
-
- public List<String> getFileFileName() {
- return fileFileName;
- }
-
- public void setFileFileName(List<String> fileFileName) {
- this.fileFileName = fileFileName;
- }
-
- public List<String> getFileContentType() {
- return fileContentType;
- }
-
- public void setFileContentType(List<String> fileContentType) {
- this.fileContentType = fileContentType;
- }
-
- public String execute() throws Exception {
- for (int i = 0; i < file.size(); i++) {
-
- uploadFile(i);
- }
- return "success";
- }
-
-
- private void uploadFile(int i) throws FileNotFoundException, IOException {
- try {
- InputStream in = new FileInputStream(file.get(i));
- String dir = ServletActionContext.getRequest().getRealPath(UPLOADDIR);
- File uploadFile = new File(dir, this.getFileFileName().get(i));
- OutputStream out = new FileOutputStream(uploadFile);
- byte[] buffer = new byte[1024 * 1024];
- int length;
- while ((length = in.read(buffer)) > 0) {
- out.write(buffer, 0, length);
- }
-
- in.close();
- out.close();
- } catch (FileNotFoundException ex) {
- ex.printStackTrace();
- } catch (IOException ex) {
- ex.printStackTrace();
- }
- }
- }
<!------------------文件名:UploadAction.java ------------------>
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
//文件上傳Action
public class UploadAction extends ActionSupport {
//上傳文件存放路徑
private final static String UPLOADDIR = "/upload";
//上傳文件集合
private List<File> file;
//上傳文件名集合
private List<String> fileFileName;
//上傳文件內容類型集合
private List<String> fileContentType;
public List<File> getFile() {
return file;
}
public void setFile(List<File> file) {
this.file = file;
}
public List<String> getFileFileName() {
return fileFileName;
}
public void setFileFileName(List<String> fileFileName) {
this.fileFileName = fileFileName;
}
public List<String> getFileContentType() {
return fileContentType;
}
public void setFileContentType(List<String> fileContentType) {
this.fileContentType = fileContentType;
}
public String execute() throws Exception {
for (int i = 0; i < file.size(); i++) {
//循環上傳每個文件
uploadFile(i);
}
return "success";
}
//執行上傳功能
private void uploadFile(int i) throws FileNotFoundException, IOException {
try {
InputStream in = new FileInputStream(file.get(i));
String dir = ServletActionContext.getRequest().getRealPath(UPLOADDIR);
File uploadFile = new File(dir, this.getFileFileName().get(i));
OutputStream out = new FileOutputStream(uploadFile);
byte[] buffer = new byte[1024 * 1024];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
in.close();
out.close();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
struts.xml配置文件中有關文件上傳的配置:
- <!--------------------文件名:struts.xml------------------->
- <struts>
- <!-- 系統常量定義,定義上傳文件字符集編碼 -->
- <constant name="struts.i18n.encoding" value="gb2312"></constant>
- <!-- 系統常量定義,定義上傳文件臨時存放路徑 -->
- <constant name="struts.multipart.saveDir" value="c:\"></constant>
- <!-- Action所在包定義 -->
- <package name="C04.4" extends="struts-default">
- <!-- Action名字,類以及導航頁面定義 -->
- <!-- 通過Action類處理才導航的的Action定義 -->
- <action name="upload" class="action.UploadAction">
- <result name="input">/jsp/upload.jsp</result>
- <result name="success">/jsp/result.jsp</result>
- </action>
- </package>
- </struts>
<!--------------------文件名:struts.xml------------------->
<struts>
<!-- 系統常量定義,定義上傳文件字符集編碼 -->
<constant name="struts.i18n.encoding" value="gb2312"></constant>
<!-- 系統常量定義,定義上傳文件臨時存放路徑 -->
<constant name="struts.multipart.saveDir" value="c:\"></constant>
<!-- Action所在包定義 -->
<package name="C04.4" extends="struts-default">
<!-- Action名字,類以及導航頁面定義 -->
<!-- 通過Action類處理才導航的的Action定義 -->
<action name="upload" class="action.UploadAction">
<result name="input">/jsp/upload.jsp</result>
<result name="success">/jsp/result.jsp</result>
</action>
</package>
</struts>
(1):文件上傳頁面如圖4.8所示。
圖4.8 文件上傳
(2):選擇文件如圖4.9所示。
圖4.9 選擇上傳的文件
(3):單擊“提交”按鈕后文件上傳成功頁面,并顯示上傳文件名,如圖4.10所示。
圖4.10 上傳文件成功后效果
(4):兩個被上傳文件最終在服務器上存放路徑效果如圖4.11所示。
圖4.11 上傳文件存放路徑圖
代碼解釋
(1)在upload.jsp中通過Form標簽和File標簽定義了兩個上傳文件。Struts2標簽筆者會在之后章節里具體介紹,這里只是讓讀者知道是如何使用標簽顯示圖4.8顯示的內容。如果上傳成功,筆者在result.jsp中“[”和“]”之間顯示上傳文件的文件名,如果是多個文件,以“,”相隔。這些顯示格式都是用Property標簽定義的。
注意:如果上傳文件,在JSP的Form中一定要定義如upload.jsp文件中黑體表示的部分。method和enctype屬性都必須要如代碼中所示。這樣Form中上傳文件才會起作用。
(2)UploadAction文件中先定義了常量UPLOADDIR,它是上傳文件上傳后存放的文件夾名字。比如筆者使用的是JBoss(附錄中有安裝和在MyEclipse中部署的操作說明),則在它的已部署Web項目下的upload文件夾中,會有所有上傳成功的文件。如圖4.11讀者也可以看見它的上傳文件最終存放路徑。
注意:在MyEclipse中開發的“WebRoot”目錄下也要新建一個upload文件夾,否則部署后在JBoss的已部署Web項目下將沒有upload文件夾。因為部署的時候會將所有“WebRoot”目錄下的文件夾和文件都部署到JBoss的已部署Web項目下。
定義好UPLOADDIR后,在定義上傳文件的屬性變量。也許其中的“fileFileName”和“fileContentType”讀者看了有點別扭,尤其是“fileFileName”感覺不符合Java命名規范,但是這兩個屬性變量是4.1小節中介紹的“fileUpload”攔截器類中的類公有變量名字,只有這樣定義,UploadAction執行時候會把在頁面上選擇的上傳文件的屬性值放在這兩個變量里面,否則調試UploadAction時候會發現這兩個變量都會是“null”即空值。不相信的讀者可以自行改變這兩個變量名再執行上傳文件功能進行調試看一下這兩個變量得到的值。
注意:因為這里筆者是進行多個文件上傳功能開發,因此“file”、“fileFileName”、“fileFileName”屬性變量都設定為List類型,其實還可以設定為數組類型。個人覺得沒有啥大區別。完全憑個人喜好而定。還有如果讀者自己開發單個文件上傳,就沒必要把它們設定為List類型或數組類型。直接把“file”定義為Java的IO包中的File類型,“fileFileName”、“fileFileName”定義為普通的String類型即字符串類型。
之后在execute方法中,寫一個循環,對所有頁面中選擇的上傳文件一個個進行上傳。這里筆者運用了重構中的“抽取方法”的方式,將上傳文件的功能封裝成一個私有方法,名字為“uploadFile”。其中運用了Java的IO包中很多API方法。有對重構和Java的IO功能不了解的讀者可以去查閱相關資料去理解掌握,這里不是本書以及本節重點,因此不再具體記述。
(3)struts.xml中定義了<constant>標簽,主要定義了文件名和文件內容顯示的字符編碼集以及這些被上傳文件臨時存放路徑。
先說明一下<constant>標簽,顧名思義這是定義整個Web項目的一些常量屬性值,如果不定義則在Struts2自帶的default.properties(讀者們可到自己安裝Struts2的文件路徑src\core\src\main\resources\org\apache\struts2\下找到)文件中有這些常量的定義,比如在本節struts.xml文件中的“struts.i18n.encoding”和“struts.multipart.saveDir”在default.properties定義代碼如下:
- <!--------------------文件名:default.properties---------------->
- ### This can be used to set your default locale and encoding scheme
- # struts.locale=en_US
- struts.i18n.encoding=UTF-8
-
- ### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data
- # struts.multipart.parser=cos
- # struts.multipart.parser=pell
- struts.multipart.parser=jakarta
- # uses javax.servlet.context.tempdir by default
- struts.multipart.saveDir=
<!--------------------文件名:default.properties---------------->
### This can be used to set your default locale and encoding scheme
# struts.locale=en_US
struts.i18n.encoding=UTF-8
### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data
# struts.multipart.parser=cos
# struts.multipart.parser=pell
struts.multipart.parser=jakarta
# uses javax.servlet.context.tempdir by default
struts.multipart.saveDir=
如果不在struts.xml文件中定義,則Web項目會缺省使用default.properties文件中這兩個常量屬性的定義。一個將使字符編碼集變為“UTF-8”,另一個干脆沒有任何文件路徑指定。而筆者開發的該Web項目缺省支持的字符編碼集是“gb2312”,而且需要指定臨時上傳文件存放路徑。(當然如果讀者開發的Web項目缺省編碼集就是“UTF-8”,而且也并不需要指定臨時路徑時候,就沒必要在struts.xml中定義這兩個<constant>),因此有必要定義這兩個屬性符合項目開發要求。
注意:也可以如第3章那樣,把這兩個屬性定義在自定義的struts.properties文件中,具體代碼可以如下:
- <!------------------------文件名:struts.properties------------------>
- struts.i18n.encoding =gb2312
- struts.multipart.saveDir= c:\
<!------------------------文件名:struts.properties------------------>
struts.i18n.encoding =gb2312
struts.multipart.saveDir= c:\
筆者個人認為比在struts.xml中定義更加好,畢竟Struts2自己也是定義在properties屬性文件中,而不是定義在自己的xml配置文件中。(Struts2自帶的xml配置文件為struts-default.xml,在4.1小節中已記述)。這里是為了讓讀者知道struts.xml配置文件也可以配置這些屬性,因此寫在struts.xml配置文件中。從3.2小節筆者說明struts.xml配置文件時并沒有介紹<constant>標簽這點也可以知道筆者個人其實是不贊同這樣的配置手段即在struts.xml中配置<constant>標簽。
在<Action>標簽中配置“result”,和第3章類似,將這兩個JSP文件的導航流程配置好即可。
(4)開始進行文件上傳功能展示,按照如上記述的步驟執行即可。筆者在桌面上新建了兩個文本文件,將它們上傳到JBoss已部署的Web項目中展示文件上傳的upload文件夾下。如圖4.11所示。
其實還可以指定上傳文件的格式,讓它只上傳特定類型的文件。比如只能上傳文本和xml文件,則在struts.xml需要顯示配置“uploadFile”攔截器。如下代碼:
- <!-----------------------文件名:struts.xml------------------>
- <struts>
- <!-- Action所在包定義 -->
- <package name="C04.4" extends="struts-default">
- <!-- Action名字,類以及導航頁面定義 -->
- <!-- 通過Action類處理才導航的的Action定義 -->
- <action name="upload" class="action.UploadAction">
- <result name="input">/jsp/upload.jsp</result>
- <result name="success">/jsp/result.jsp</result>
- </action>
- <!—顯示配置文件上傳攔截器 -->
- <interceptor-ref name=”fileUpload”>
- <!—指定特定類型的上傳文件 -->
- <param name =”allowedTypes”>text/plain,application/xml</param>
- </ interceptor-ref >
- <interceptor-ref name=”defaultStack”></ interceptor-ref >
- </package>
- </struts>
<!-----------------------文件名:struts.xml------------------>
<struts>
<!-- Action所在包定義 -->
<package name="C04.4" extends="struts-default">
<!-- Action名字,類以及導航頁面定義 -->
<!-- 通過Action類處理才導航的的Action定義 -->
<action name="upload" class="action.UploadAction">
<result name="input">/jsp/upload.jsp</result>
<result name="success">/jsp/result.jsp</result>
</action>
<!—顯示配置文件上傳攔截器 -->
<interceptor-ref name=”fileUpload”>
<!—指定特定類型的上傳文件 -->
<param name =”allowedTypes”>text/plain,application/xml</param>
</ interceptor-ref >
<interceptor-ref name=”defaultStack”></ interceptor-ref >
</package>
</struts>
定義了一個名為“allowedTypes”的參數,其中在<param></param>之間的是文件類型,也可以用“,”間隔,表示允許上傳多個文件類型。這里允許上傳文件類型為txt、xml格式的文件。如果讀者不知道各個文件類型的定義,可在自己的JBoss安裝目錄中的server\default\deploy\jboss-web.deployer\conf\下的web.xml文件中找到(搜索<mime-mapping>即可)。
注意:如果顯示配置Struts2自己的缺省攔截器一定要寫在“defaultStack”前,否則“fileUpload”攔截器不會執行攔截。因為Struts2中如果某個攔截器執行攔截時候發現自己已經執行過,第二個乃至之后同名的攔截器都不會執行。這里因為“defaultStack”攔截器棧中包含了“fileUpload”攔截器,而“fileUpload”攔截器已經執行攔截了,則不會再執行攔截。如果把“defaultStack”攔截器棧放在“fileUpload”攔截器前配置,則只執行“defaultStack”攔截器棧中的“fileUpload”攔截器,這里是沒有定義“allowedTypes”的,Struts2缺省默認的是支持所有文件類型。因此它會支持所有文件類型的文件上傳。因此再設定“allowedTypes”就沒有任何意義了。
posted on 2009-04-13 15:33
lanxin1020 閱讀(234)
評論(0) 編輯 收藏 所屬分類:
struts2