web应用下上传文件需要为表单设置enctype="multipart/form-data"属性,表单将以二进制编码的方式提交请求,然后由解析器进行解析,struts2不提供解析器,但可以和common-fileupload、COS很好的结合。struts2默认使用Jakarta的common-fileupload文件上传框架(在struts2-core.jar中default.properties中可见struts.multipart.parser=jakarta)。
下面展示一个使用common-fileupload实现文件上传的示例。
1、从http://commons.apache.org/上下载commons-fileupload-1.2.1.jar和commons-io-1.3.2.jar,然后放到WEB-INF/lib文件夹下。
2、编写代码
upload-input.jsp
- <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
- <%@taglib prefix="s" uri="/struts-tags" %>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>文件上传</title>
- </head>
- <body>
- <s:fielderror></s:fielderror>
- <form action="upload.action" method="post" enctype="multipart/form-data">
- 标题:<input type="text" name="title">
- <br/>
- 文件:<input type="file" name="file">
- <br>
- <input type="submit" value="上传">
- </form>
- </body>
- </html>
upload.jsp
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>文件上传</title>
- </head>
- <body>
- 标题:${title}
- <br/>
- 文件:${fileFileName }
- <br>
- </body>
- </html>
UploadAction.java
- package com.petrochina.action.business;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.InputStream;
- import java.io.OutputStream;
- import org.apache.commons.io.IOUtils;
- import org.apache.struts2.ServletActionContext;
- import com.opensymphony.xwork2.ActionSupport;
- public class UploadAction extends ActionSupport {
- private static final long serialVersionUID = 1L;
- private File file;// 对应文件域的file,封装文件内容
- private String fileContentType;// 封装文件类型
- private String fileFileName;// 封装文件名
- private String savePath;// 保存路径
- private String title;// 文件标题
- @Override
- public String execute() throws Exception {
- if (file != null) {
- // System.out.println(getFileContentType());
- // 读取文件内容到InputStream里
- InputStream is = new FileInputStream(getFile());
- // 创建输出流,生成新文件
- OutputStream os = new FileOutputStream(getSavePath() + "//" + getFileFileName());
- // 将InputStream里的byte拷贝到OutputStream
- IOUtils.copy(is, os);
- os.flush();
- IOUtils.closeQuietly(is);
- IOUtils.closeQuietly(os);
- return SUCCESS;
- }
- return INPUT;
- }
- public File getFile() {
- return file;
- }
- public void setFile(File file) {
- this.file = file;
- }
- public String getFileContentType() {
- return fileContentType;
- }
- public void setFileContentType(String fileContentType) {
- this.fileContentType = fileContentType;
- }
- public String getFileFileName() {
- return fileFileName;
- }
- public void setFileFileName(String fileFileName) {
- this.fileFileName = fileFileName;
- }
- public String getSavePath() {
- // 将相对路径转换成绝对路径
- return ServletActionContext.getServletContext().getRealPath(savePath);
- }
- public void setSavePath(String savePath) {
- this.savePath = savePath;
- }
- public String getTitle() {
- return title;
- }
- public void setTitle(String title) {
- this.title = title;
- }
- }
struts.xml
- <struts>
- <!-- struts常量定义 -->
- <!-- 指定struts国际化资源文件的baseName -->
- <constant name="struts.custom.i18n.resources" value="messageResource"/>
- <!-- 指定每次HTTP请求时是否重新加载国际化资源文件,默认为false,开发阶段设为true -->
- <constant name="struts.i18n.reload" value="true"/>
- <!-- 配置应用的编码方式 -->
- <constant name="struts.i18n.encoding" value="UTF-8"/>
- <!-- struts.xml变更时是否自动重新加载 -->
- <constant name="struts.configuration.xml.reload" value="true"/>
- <!-- 限定上传文件最大大小4M,struts2默认maxSize为2M -->
- <constant name="struts.multipart.maxSize" value="4194304"></constant>
- <!-- 指定上传文件时临时文件的存放路径,设为"/tempUpload"将在 项目所在盘下创建文件夹tempUpload-->
- <constant name="struts.multipart.saveDir" value="/tempUpload"></constant>
- <!-- action 定义 -->
- <package name="mystruts" extends="struts-default">
- <action name="upload" class="com.petrochina.action.business.UploadAction">
- <!-- 配置fileUpload拦截器 -->
- <interceptor-ref name="fileUpload">
- <!-- 配置允许上传的文件类型-->
- <param name="allowedTypes">image/x-ms-bmp,image/jpeg,image/gif,image/png,image/x-png,application/excel,application/vnd.ms-excel</param>
- <!-- 配置允许上传的文件大小 -->
- <param name="maximumSize">2048000</param>
- </interceptor-ref>
- <interceptor-ref name="defaultStack"></interceptor-ref>
- <!-- 配置上传文件的保存的相对路径 -->
- <param name="savePath">/test</param>
- <!-- 配置逻辑视图和实际资源的对应关系 -->
- <result>/WEB-INF/content/business/upload.jsp</result>
- <result name="input">/WEB-INF/content/business/upload-input.jsp</result>
- </action>
- </package>
- </struts>
效果如下:
上传页面:
上传成功:
项目结构图:
可见,成功在webapp/test/下上传了upload.png文件。
在struts.xml中配置fileUpload拦截器来限制上传文件的类型和大小时需要注意:
1、通过allowedTypes参数限制文件类型时允许类型定义要全,比如png类型的图片就有image/png和image/x-png两种类型,我开始只定义了image/png,发现png类型的图片上传不了,后来看了http://exceljava.javaeye.com/blog/210249发现我上传的图片类型是image/x-png,添加以后上传成功,所以遇到上传类型错误最好在本机输入看看是什么类型,然后在allowedTypes参数中添加。
2、通过maximunSize参数限制上传的文件大小时,如果没有改变常量“struts.multipart.maxSize”的值,那么maximunSize就不要设置超过2M,否则程序直接抛出异常,拦截器不会拦截,因为fileUpload拦截器默认使用“struts.multipart.maxSize”的值作为上传文件的最大值。当然,可以在struts.xml或者struts.properties中更改“struts.multipart.maxSize”的值,然后确保maximunSize参数的值不大于“struts.multipart.maxSize”的值。
3、对于拦截器的报错信息可以在国际化资源文件中增加
struts.messages.error.file.too.large=your error message
struts.messages.error.content.type.not.allowed=your error message