>>尽可能以POST请求方式上传,由于GET支持文件大小是有限制的。html
>>必需要加上enctype="multipart/form-data"表示上传的文件,以随着请求体通过特殊编码后,一同传入服务器java
>>每一个表单项,必须取一个名字(name),由于服务器端便于经过名字(name)收集信息.web
private String uploadContentType;//上传文件的类型,(Fileupload拦截器传入的参数) private File upload;//上传的文件,(Fileupload拦截器传入的参数) private String uploadFileName;//上传文件的真实文件名,(Fileupload拦截器传入的参数)
与jsp页面中的name相对应.apache
注意:upload和表单项与<s:file>中的name属性一致浏览器
upload拼上contentType其中C要大写.安全
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!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>Insert title here</title>
</head>
<body>
<s:form action="UploadAction" enctype="multipart/form-data" method="POST">
<s:textfield name="username"/>
<s:file name="upload" />
<s:submit value="提交"/>
</s:form>
</body>
</html>
在默认栈中,有一个fileUpload文件上传拦截器,可是没有下载拦截器,源码参见struts2-core-2.3.16-sources.jar/struts-default.xml服务器
UploadAction.java框架
package action; import java.io.File; import com.opensymphony.xwork2.ActionSupport; /** * @ClassName: UploadAction * @Description: 文件上传 * @author: amosli * @email:amosli@infomorrow.com * @date Jan 14, 2014 1:50:28 AM */ public class UploadAction extends ActionSupport { private static final long serialVersionUID = -8920466592471253212L; private String username;// 用户名 private String uploadContentType;// 上传文件的类型,(Fileupload拦截器传入的参数) private File upload;// 上传的文件,(Fileupload拦截器传入的参数) private String uploadFileName;// 上传文件的真实文件名,(Fileupload拦截器传入的参数) public void setUsername(String username) { this.username = username; } public void setUploadContentType(String uploadContentType) { this.uploadContentType = uploadContentType; } public void setUpload(File upload) { this.upload = upload; } public String getUsername() { return username; } public String getUploadContentType() { return uploadContentType; } public File getUpload() { return upload; } public String getUploadFileName() { return uploadFileName; } public void setUploadFileName(String uploadFileName) { this.uploadFileName = uploadFileName; } public String uploadMethod() { return SUCCESS; } }
upload_success.jspeclipse
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!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>Insert title here</title> </head> <body> 恭喜,上传文件成功! <hr> </body> </html>
upload.xmljsp
<?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> <package name="upload" namespace="/" extends="struts-default"> <action name="UploadAction" class="action.UploadAction" method="uploadMethod"> <result name="success" type="dispatcher"> /WEB-INF/upload_success.jsp </result> </action> </package> </struts>
struts.xml
<?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>
<!-- 加载其余配置文件 -->
<include file="config/upload.xml"></include>
</struts>
程序运行逻辑:
浏览器中输入:http://localhost:8080/struts2_learn/upload.jsp---》输入用户名,选择要上传的文件---》点击提交---》触发UploadAction---》从内存中查找对应的配置文件struts.xml->upload.xml->UploadAction.java,若调用成功--》数据转发到upload_success.jsp。
成功上传提示:
1)如何将上文件上传者的姓名显示出来,如何将文件类型,以及文件名显示出来?将upload_success.jsp改写以下:
<body>
恭喜,上传文件成功!
<hr>
<b>上传用户名:</b> <s:property value="username"/><br>
<b>文件类型:</b> <s:property value="uploadContentType"/><br>
<b>上传的文件:</b> <s:property value="upload"/><br>
<b>上传文件的真实文件名:</b> <s:property value="uploadFileName"/><br>
</body>
上面是经过struts2的标签进行获取对应的属性值,这里的value与定义UploadAction.java中定义的必须一致,而且提供get()方法。下面看效果:
这里上传一个大小为9M多的文件,struts-2.3.16-docs.zip,看提示以下图所示。
浏览器中的提示以下:
eclipse终端提示为:
从上面提示能够看到maximum (2097152),计算下来为2M,这个是哪里配置得来的??
>>>查看源码包中,struts2-core-2.3.16-sources.jar/org/apache/struts2/default.properties中有配置为:struts.multipart.maxSize=2097152
同时底层源码显示struts.multipart.parser=jakarta,使用的是jakarta开源组件完成上传的,和传统web应用是同样的,struts2只是将其封装了而已。
如何才能上传大一点的文件呢?很显然必须把默认的配置改掉
在upload_struts.xml中添加下面常量,将默认值改成20M从新上传
<constant name="struts.multipart.maxSize" value="20971520"></constant>
注意:上面更改的是上传文件的总大小,全部上传文件的大小之和。
结果:
查看org.apache.struts2.interceptor.FileUploadInterceptor拦截器的源码,其中有setMaximumSize,这里maximumSize就是单个文件的大小进行设置。
配置upload.xml文件:
<?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.multipart.maxSize" value="20971520"></constant> <!-- 对上传文件总大小进行设置 --> <package name="upload" extends="struts-default"> <action name="UploadAction" class="action.UploadAction" method="uploadMethod"> <result name="success" type="dispatcher"> /WEB-INF/upload_success.jsp </result> <!-- 对系统的拦截器进行设置 --> <interceptor-ref name="fileUpload"> <!-- 对单个上传文件的大小进行设置,5M--> <param name="maximumSize">5242880</param> </interceptor-ref> </action> </package> </struts>
结果:
此时的UserAction.java为
package action; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import javax.servlet.ServletContext; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; /** * @ClassName: UploadAction * @Description: 文件上传 * @author: amosli * @email:amosli@infomorrow.com * @date Jan 14, 2014 1:50:28 AM */ public class UploadAction extends ActionSupport { private static final long serialVersionUID = -8920466592471253212L; private String username;// 用户名 private String uploadContentType;// 上传文件的类型,(Fileupload拦截器传入的参数) private File upload;// 上传的文件,(Fileupload拦截器传入的参数) private String uploadFileName;// 上传文件的真实文件名,(Fileupload拦截器传入的参数) public void setUsername(String username) { this.username = username; } public void setUploadContentType(String uploadContentType) { this.uploadContentType = uploadContentType; } public void setUpload(File upload) { this.upload = upload; } public String getUsername() { return username; } public String getUploadContentType() { return uploadContentType; } public File getUpload() { return upload; } public String getUploadFileName() { return uploadFileName; } public void setUploadFileName(String uploadFileName) { this.uploadFileName = uploadFileName; } public String uploadMethod() throws Exception { ServletContext context = ServletActionContext.getServletContext(); String real_path = context.getRealPath("/WEB-INF/upload/"); InputStream inputStream = new FileInputStream(upload); OutputStream outputStream = new FileOutputStream(real_path+"/"+uploadFileName); byte[] b = new byte[1024]; int len = 0 ; while((len=inputStream.read(b))>0){ outputStream.write(b, 0, len); } //关闭流 inputStream.close(); outputStream.close(); //删除tmp文件,最好是用tyrcatch finally进行删除 upload.delete(); return SUCCESS; } }
为何会指针的错误???
当一个<action>标签,不引用任何拦截器时,默认会执行defaultStack中的18个拦截器;
当引用指定的拦截器时,将不会执行默认的拦截器。
因此若是只指定执行FileUploadInterceptor时,其它拦截器不执行将不能进行注解操做,即会产生空指针错误。
那么如何使用指定的拦截器和默认的拦截器同时工做呢??
<!-- 显示引用默认的拦截器 --> <interceptor-ref name="defaultStack"></interceptor-ref>
只须要在<action>标签中再填加名称为defaultStack的拦截器引用便可。
从新上传9.1M的文件后,结果以下:
这里只须要在upload.xml中配置 名称为input的result属性便可,再将数据转发到upload.jsp页面。
<result name="input" type="dispatcher">
upload.jsp
</result>
结果以下:
5)、如何对上传文件的扩展名加以限制??
<!-- 对系统的拦截器进行设置 --> <interceptor-ref name="fileUpload"> <!-- 对单个上传文件的大小进行设置,5M--> <param name="maximumSize">5242880</param> <!-- 对容许的文件扩展名进行设置,这里以英文逗号隔开 --> <param name="allowedExtensions">.txt,.xml</param> </interceptor-ref>
这里只容许.txt和.xml文件上传,上传一个.html文件和一个.txt文件验证是否有效。
但实际状况很容易就能够更改扩展名,因此实质上对提交安全性效果不是特别大。
<!-- 对系统的拦截器进行设置 --> <interceptor-ref name="fileUpload"> <!-- 对单个上传文件的大小进行设置,5M--> <param name="maximumSize">5242880</param> <!-- 对容许的文件扩展名进行设置,这里以英文逗号隔开 --> <param name="allowedExtensions">.txt,.xml</param> <!-- 对容许的文件类型进行设置,这里以英文逗号进行隔开 --> <param name="allowedTypes">text/plain,text/xml</param> </interceptor-ref>
这里文件类型是没办法人工去更改的,因此可以较扩展名来讲实质上拦截效果更强,与上面很相似,这里就再也不演示,其中须要注意的是文件类型不要写错了。
提示信息在:/org/apache/struts2/struts-messages.properties
默认配置在:/org/apache/struts2/default.properties
default.properties 会加载struts-messages.properties,因此这里能够写个properties进行覆盖原始文件。