struts2沒有提供自己的請求解析器,也就是說,struts2不會自己去處理multipart/form-data的請求,它需要調用其他請求解析器,將HTTP請求中的表單域解析出來,但struts2在原有的上傳解析器上作了進一步封裝,更進一步簡化了文件上傳,Struts2的struts.properties配置文件中,配置struts2的上傳文件解析器struts.multipart.parser=jakarta(srtuts2默認),也可以設置為常用的cos,pell等。項目結構示意圖:web.xml文件內容:<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>struts-cleanup</filter-name>
<filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class>
</filter>
<filter-mapping>
<filter-name>struts-cleanup</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
這裡web.xml多配置了一個ActionContextCleanUp的配置,這個類是一個filter,他的作用是方便strut2與sitemesh整合,與文件上傳本沒有關系,但不加載這個filter,可能在上傳中出現莫名的異常,加入後就穩定了,可能是strut2的bug吧。index.jsp文件內容:<%@page language="java" pageEncoding="GBK"%><%@taglib prefix="s" uri="/struts-tags"%><%@taglib prefix="c" uri="http://java.sun.com/jstl/core_rt"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> ${requestScope.typeError} <form action="upload.action" method="post" enctype="multipart/form-data"> <input type="text" name="title" /> <br> <input type="file" name="upload" /> <br> <input value="upload" type="submit" /> </form> </body></html>success.jsp文件內容:<%@ page language="java" pageEncoding="GBK"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head> <body> 上傳成功! <br> 文件標題: <s:property value=" + title" /> <br> 文件為: <img src="<s:property value="'upload/' + uploadFileName"/>" /> <br> </body></html>struts.properties文件內容:struts.locale=zh_CNstruts.i18n.encoding=GBKstruts.multipart.parser=jakartastruts.xml文件內容:<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"><struts> <include file="struts-default.xml" /> <constant name="struts.multipart.maxSize" value="20971520" /> <constant name="struts.custom.i18n.resources" value="globalMessages" /> <constant name="struts.i18n.encoding" value="GBK" /> <package name="lee" extends="struts-default"> <action name="upload" class="lee.UploadAction"> <param name="allowTypes"> image/pjpeg,image/bmp,image/jpg,image/png,image/gif,image/jpeg </param> <param name="savePath">/upload</param> <result>/success.jsp</result> <result name="input">/index.jsp</result> </action> </package></struts>參看tomcat的web.xml中的mime:<mime-mapping> <extension>gif</extension> <mime-type>image/gif</mime-type></mime-mapping>UploadAction.java文件內容:package lee;import java.io.*;import com.opensymphony.xwork2.ActionContext;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.ActionSupport;public class UploadAction extends ActionSupport { private String title; private File upload; private String uploadContentType; private String uploadFileName; private String allowTypes; // 接受依賴注入的屬性 private String savePath; // 接受依賴注入的方法 public void setSavePath(String value) { this.savePath = value; } private String getSavePath() throws Exception { return ServletActionContext.getServletContext().getRealPath(savePath); } public void setTitle(String title) { this.title = title; } public void setUpload(File upload) { this.upload = upload; } public void setUploadContentType(String uploadContentType) { this.uploadContentType = uploadContentType; } public void setUploadFileName(String uploadFileName) { this.uploadFileName = uploadFileName; } public String getTitle() { return (this.title); } public File getUpload() { return (this.upload); } public String getUploadContentType() { return (this.uploadContentType); } public String getUploadFileName() { return (this.uploadFileName); } @Override public String execute() throws Exception { System.out.println("開始上傳單個文件---"); System.out.println(getSavePath()); System.out.println("==========" + getUploadFileName()); System.out.println("==========" + getUploadContentType()); System.out.println("==========" + getUpload()); // 判斷是否允許上傳 String filterResult = filterType(this.getAllowTypes().split(",")); if (filterResult != null) { ActionContext.getContext().put("typeError","您要上傳的文件類型不正確"); return filterResult; } // 以服務器的文件保存地址和原文件名建立上傳文件輸出流 FileOutputStream fos = new FileOutputStream(getSavePath() + "\\" + getUploadFileName()); FileInputStream fis = new FileInputStream(getUpload()); byte[] buffer = new byte[1024]; int len = 0; while ((len = fis.read(buffer)) > 0) { fos.write(buffer, 0, len); } return SUCCESS; } public String filterType(String[] types) { String fileType = this.getUploadContentType(); for (String type : types) { if (type.equals(fileType)) { return null; } } return INPUT; } public String getAllowTypes() { return allowTypes; } public void setAllowTypes(String allowTypes) { this.allowTypes = allowTypes; }}Struts2針對表單中名為xxx的文件域,在對應的Action類中使用3個屬性來封裝該文件域信息:
1.類型為File的xxx屬性:用來封裝頁面文件域對應的文件內容。
2.類型為String的xxxFileName屬性:用來封裝該文件域對應的文件的文件名。
3.類型為String的xxxContentType屬性:用來封裝該文件域應用的文件的文件類型。以上程序調試通過!