首先肯定是要配置好struts2環境,這個在另一篇《struts2環境搭建,以及一個簡單實例》里已經講過了
首先是網頁部分,upload_file.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML> <html> <head> <title>Upload File</title> </head> <body> <form action="UploadFile" method="post" enctype="multipart/form-data"> <!--文件域--> <input type="file" name="source" /> <input type="submit" value="上傳"> </form> </body> </html>
上傳文件的表單,metho必須設置成post,enctype必須設置成multipart/form-data。
從上面代碼中可以看到這個表單提交給了UploadFile這個action來處理,那我們在struts.xml里面配置如下:
<action name="UploadFile" class="com.lidi.action.UploadAction"> <result name="success">/uploadResult.jsp</result> <!--fileUpload攔截器,可用於限制上傳文檔的類型和文檔大小 --> <interceptor-ref name="fileUpload"> <!-- 限制文件大小20M,單位為字節 --> <param name="maximumSize">20971520</param> </interceptor-ref> <!--默認攔截器,必須聲明在fileUpload攔截器之后 --> <interceptor-ref name="defaultStack" /> </action>
fileUpload攔截器,用於設置上傳路徑,限制文件類型和大小。
關於限制文件大小,光有<param name="maximumSize">是不行的,還必須在<struts>標簽下添加
<constant name="struts.multipart.maxSize" value="21000000"/>
這行代碼表示整個項目所有要上傳文件的地方允許上傳的文件大小的最大值,也就是說這個項目里上傳的任何單個文件大小不能超過21000000字節(約20M),如果項目中不添加這行代碼,則默認允許上傳的文件大小最大為2M,所以這也是突破struts2只能上傳2M文件的限制的方法。
關於限制文件類型,如果需要限制為圖片文件,則<interceptor>可以這樣配置
<!-- 設置只允許上傳圖片文件 --> <intercepter-ref name="fileUpload"> <param name="allowedTypes">image/bmp, image/x-png, image/gif, image/jpeg</param> </intercepter-ref> <interceptor-ref name="defaultStack" />
<param name="allowedTypes">標簽中的值都是文件的MIME類型,常用文件的MIME類型可以在%TOMCAT_HOME%\conf\web.xml中找到。
如果要限制為word文件,則可以<interceptor>可以這樣配置
<!-- 設置只允許上傳word文檔 --> <intercepter-ref name="fileUpload"> <param name="allowedTypes">application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document</param> </intercepter-ref> <interceptor-ref name="defaultStack" />
然而我感覺這樣來限制文件類型,不如用javascript在前端實現限制。
接下來寫UploadAction,UploadAction必需的私有屬性是source,這是和upload_file.jsp里面文件域的name屬性是一致,就是說文件域的name屬性值為source,則UploadAction中必需有私有屬性source,另外,還有兩個比較重要的私有屬性:
private String sourceFileName; //待上傳文件的文件名 private String sourceContentType; //待上傳文件的文件類型
這兩個變量名的格式就是前面的前綴source和upload_file.jsp中的文件域的name屬性相同。
綜合來說,就是,比如upload_file.jsp中文件域的name = “abc”,則Action中就需要這樣定義
private File abc; private String abcFileName; private String abcContentType;
abc會自動獲取要上傳的文件對象,abcFileName自動獲取文件名,abcContentType自動獲取文件類型。
關於上傳路徑,是我要重點說一下的。
如果是上傳到絕對路徑,那還挺好搞的,但如果要上傳到項目根目錄下的upload文件夾呢,怎么獲得這個upload文件夾的完整路徑?
我嘗試過使用
ServletActionContext.getServletContext().getRealPath("/upload");
但返回了null。也用過
ServletActionContext.getRequest().getRealPath("/upload");
還是返回了null。但在網上查下這個問題,很多人都推薦這么寫,證明可能某些情況下這樣寫確實是可行的,但也有跟我一樣返回null的人,他們同時推薦了一種新的方法,就是讓UploadAction實現ServletContextAware接口。具體做法如下:
public class UploadAction extends ActionSupport implements ServletContextAware { /** * 省略其它代碼... */ private ServletContext context; public ServletContext getContext() { return context; } public void setContext(ServletContext context) { this.context = context; } @Override public void setServletContext(ServletContext context) { this.context = context; } }
然后使用
String path = context.getRealPath("/upload");// 重要:斜杠不能少
獲得upload文件夾的路徑。然后執行上傳:
/*將文件上傳到upload文件夾下*/ File savefile = new File(path, sourceFileName); FileUtils.copyFile(source, savefile);
我個人是比較推薦這種方法的,因為這種方法好像規避了當項目被打包轉移到其它環境時也能保證獲得正確的路徑。
后面貼上UploadAction的完整代碼UploadAction.java

package com.lidi.action; import java.io.File; import java.io.IOException; import javax.servlet.ServletContext; import org.apache.commons.io.FileUtils; import org.apache.struts2.util.ServletContextAware; import com.opensymphony.xwork2.ActionSupport; public class UploadAction extends ActionSupport implements ServletContextAware { /** * */ private static final long serialVersionUID = 1L; private File source;// 待上傳文件 private String sourceFileName;// 待上傳文件的文件名 private String sourceContentType; // 待上傳文件的文件類型 private ServletContext context; // 重要 /* 重要 */ public ServletContext getContext() { return context; } public void setContext(ServletContext context) { this.context = context; } /* getters & setters */ public File getSource() { return source; } public void setSource(File source) { this.source = source; } public String getSourceFileName() { return sourceFileName; } public void setSourceFileName(String sourceFileName) { this.sourceFileName = sourceFileName; } public String getSourceContentType() { return sourceContentType; } public void setSourceContentType(String sourceContentType) { this.sourceContentType = sourceContentType; } @Override public void setServletContext(ServletContext context) { this.context = context; } public String execute() throws IOException { /*獲取存放上傳文件的路徑:項目根目錄upload文件夾*/ String path; path = context.getRealPath("/upload");// 重要:斜杠不能少 System.out.println(path); /*將文件上傳到upload文件夾下*/ File savefile = new File(path, sourceFileName); FileUtils.copyFile(source, savefile); System.out.println(savefile.getAbsolutePath()); return SUCCESS; } }
上傳結果頁uploadResult.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE HTML> <html> <head> <title>Upload Result</title> </head> <body> <p>文件名:<s:property value="sourceFileName" /></p> <p>文件類型:<s:property value="sourceContentType" /></p> <p>文件:<a href="upload/<s:property value="sourceFileName" />"><s:property value="sourceFileName" /></a></p> </body> </html>