在Struts2中借助Commons FileUpload组件很容易实现文件的上传与下载,Commons FileUpload通过将HTTP的数据保存到临时文件夹,然后Struts使用fileUpload拦截器将文件绑定到Action的实例中,从而我们能够以本地文件方式操作浏览器上传文件。但是这些例子大多需要在struts.xml中进行配置,比较麻烦,好在Struts2中提供了struts2-convention-plugin插件,可以在程序中使用注解对Action进行配置,使之更加灵活。
下面介绍使用注解实现文件的上传:
1. 添加依赖的jar包
2. 配置struts.xml文件,这里的struts文件基本上不需要配置,如下即可:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <constant name="struts.enable.DynamicMethodInvocation" value="true" /> <constant name="struts.devMode" value="true" /> <constant name="struts.convention.package.locators" value="action" /> <!-- 指定允许上传的文件最大字节数,默认值是2097152(2M),使用struts常量扩大默认上传文件大小 --> <constant name="struts.multipart.maxSize" value="104857600"></constant> </struts>3. 编写文件上传的Action:FileUploadAction.java
package com.figo.action; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import org.apache.struts2.ServletActionContext; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.InterceptorRef; import org.apache.struts2.convention.annotation.InterceptorRefs; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; import com.opensymphony.xwork2.ActionSupport; @Action("fileUpload") @InterceptorRefs(value = { @InterceptorRef("fileUploadStack") }) @Results({ @Result(name = "success", location = "/result.jsp") }) public class FileUploadAction extends ActionSupport { private static final long serialVersionUID = 572146812454l; private static final int BUFFER_SIZE = 16 * 1024; // 封装上传文件域的属性 private File upload; // 封装上传文件类型的属性 private String contentType; // 封装上传文件名的属性 private String fileName; private String storageFileName; // private String storagePath; // since we are using <s:file name="upload" ... /> the File itself will be // obtained through getter/setter of <file-tag-name> public File getUpload() { return upload; } public void setUpload(File upload) { this.upload = upload; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } // since we are using <s:file name="upload" .../> the file name will be // obtained through getter/setter of <file-tag-name>FileName public String getUploadFileName() { return fileName; } public void setUploadFileName(String fileName) { this.fileName = fileName; } public String getStorageFileName() { return storageFileName; } public void setStorageFileName(String storageFileName) { this.storageFileName = storageFileName; } // since we are using <s:file name="upload" ... /> the content type will be // obtained through getter/setter of <file-tag-name>ContentType public String getUploadContentType() { return contentType; } public void setUploadContentType(String contentType) { this.contentType = contentType; } public String getContentType() { return contentType; } public void setContentType(String contentType) { this.contentType = contentType; } public void copy(File src, File dst) { try { InputStream in = null; OutputStream out = null; try { in = new BufferedInputStream(new FileInputStream(src), BUFFER_SIZE); out = new BufferedOutputStream(new FileOutputStream(dst), BUFFER_SIZE); byte[] buffer = new byte[BUFFER_SIZE]; while (in.read(buffer) > 0) { out.write(buffer); } } finally { if (null != in) { in.close(); } if (null != out) { out.close(); } } } catch (Exception e) { e.printStackTrace(); } } public static String getExtention(String fileName) { int pos = fileName.lastIndexOf("."); return fileName.substring(pos); } @Override public String execute() throws Exception { // storageFileName = new Date().getTime() + getExtention(fileName); storageFileName = fileName; System.out.println("FileName: " + fileName); System.out.println("ContentType: " + contentType); System.out.println("File: " + upload); File storageFile = new File(ServletActionContext.getServletContext() .getRealPath("/upload") + "/" + storageFileName); copy(upload, storageFile); return SUCCESS; } }FileUploadAction作用是将浏览器上传的文件拷贝到WEB应用程序的upload文件夹下。
4. 编写文件上传的表单页面 upload.jsp:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" > <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>File Upload</title> </head> <body> <s:form action="fileUpload" method="post" enctype="multipart/form-data"> <s:file name="upload" label="File" /> <s:submit /> </s:form> </body> </html>将表单的提交方式设为POST,然后将enctype设为multipart/form-data, <s:file/>标志将文件上传控件绑定到Action的upload属性。
5. 结果返回页面 result.jsp:
<%@ page language="java" contentType="text/html;charset=utf-8" pageEncoding="utf-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" > <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>File upload success</title> </head> <body> File <s:property value="fileName" /> upload success. <br /> Saved as <s:property value="storageFileName" /> <br /> File: <s:property value="upload" /> <br /> ContentType: <s:property value="contentType" /> </body> </html>
6. 配置web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>Upload</display-name> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> <init-param> <param-name>actionPackages</param-name> <param-value>com.figo.action</param-value> </init-param> </filter> <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> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
重点是在filter里添加<init-param>,actionPackages为Action文件所在的包。
7. 页面测试:
文件上传页面:
文件上传返回结果:
因为是在eclipse工程里进行的测试,所以文件保存在了临时文件里,如果是真正发布的话,上传的文件就会保存到预先设置好的目录中。
注:
1. struts2默认最大只能上传2M的文件,可以在struts.xml中扩大默认文件上传的大小。
2. 总结常用的注解如下:
Namespace:指定命名空间。
ParentPackage:指定父包。
Result:提供了Action结果的映射(一个结果的映射)。
Results:“Result”注解列表。
ResultPath:指定结果页面的基路径。
Action:指定Action的访问URL。
Actions:“Action”注解列表。
ExceptionMapping:指定异常映射(映射一个声明异常)。
ExceptionMappings:一级声明异常的数组。
InterceptorRef:拦截器引用。
InterceptorRefs:拦截器引用组。
这里只是给大家起个抛砖引玉的效果,程序本身很简单,主要是配置,下一篇介绍零配置文件下载。
源代码下载链接:http://download.csdn.net/detail/sxwyf248/4462899