Struts2笔记系列之文件上传下载,表单重复提交
Struts2实现文件上传
使用struts2实现文件上传,需要使用struts2预定义的fileUpload***,fileUpload***在默认的defaultStack***栈中,如果没有配置自己的***的话,Action默认继承struts-default包,而默认的***栈就在struts-default包中,因此会引用默认的***栈。
在表单中,包含了文件上传的表单域,则一定需要把整个表单enctype属性设置为multipart/form-data。其他的操作和普通的Action配置一样,表单也没有什么特殊之处。
对于上传进行限制,我们可以在引用fileUpload***的时候,指定3个参数:
allowedTypes:指定允许上传的文件的类型,如果存在多种类型,以逗号分开;
maximumSize:允许上传的文件的最大字节数;
allowedExtensions:指定允许上传的文件的扩展名。
如果上传的文件不满足以上的参数指定的条件,则会跳转到叫input的<result>上,一般input都会指回到提交之前的页面,也就是文件上传页面。
在使用struts2进行文件的上传的时候,默认上传文件的大小是不能超过2097152个字节,这个配置在struts2-core-xxx.jar中,"\org\apache\struts2“文件夹下的default.properties文件中
struts.multipart.maxSize=2097152
如果想上传更大的文件,只需要覆盖这个默认设置就可以,有两种方式:
⑴修改default.properties中的参数值
⑵在struts.xml中配置,定义常量为:
<constant name="struts.multipart.maxSize" value="1024000000"/>
在一个表单中上传多个文件的方法:
只需要在提交页面上添加同名的多个文件输入域即可, 然后再Action中对应使用File类型的数组去接收这些参数即可。
Struts2实现文件下载
struts2使用stream类型的Result,这种Result返回一个InputStream,只需要让这个InputSteam读取到用户想要下载的文件即可。在struts-default.xml中有result-type类型为stream的配置,因此用户想要使用这种类型,只需要继承struts-default包即可。
实现文件下载的Action
使用stream类型作为Result的Action和普通的Action有很大的不同,它不需要execute方法,而是需要一个公有的,返回为InputStream的getInputStream方法,这个方法用来返回文件的内容。eg:
public class loadFileAction extends ActionSupport{
public InputStream getInputStream() throws Exception{
File file = new File("D:/resource/struts.txt");
return new FileInputStream(file);
}
}
在struts.xml中配置Action
<action name="downAction" class="com.dong.loadFileAciton">
<result type="stream" >
<param name="contentDisposition">attachement;filename="struts.txt"</param>
</result>
</action>
stream类型的结果可以指定的参数有:
contentType:下载文件的类型;
contentLength:下载文件的长度,用于浏览器的进度条显示;
contentDisposition::指定文件下载的默认名字,如果不指定规则,则使用Action名.action;
inputName:用于返回InputStream的get方法的名字;
bufferSize:缓冲区大小,默认为1KB;
allowCaching:是否允许浏览器进行缓存;
contentCharSet:HTTP响应头信息中的编码方式。
下载页:
<body>
<a href="/helloworld/downAction">download the file</a>
</body>
文件名的配置:
⑴在Action中提供一个返回文件名称的方法,然后再配置文件中引用这个变量
public class downAciton extends ActionSupport{
public String FileName(){
return "struts.txt";
}
}
相应的strtus.xml中的配置
<package name="helloworld" extends="struts-default">
<action name="donwloadAction" class="xxx">
<result type="stream">
<param name="contentDisposition">attachment;filename=${downLoadFileName}</param>
</result>
</action>
</package>
⑵去掉关于配置文件中contentDisposition的配置,直接在Action中提供一个getContentDisposition方法,
public class downAction extends ActionSupport{
public String getContentDisposition(){
return "attachment;filename="strtus.txt";
}
public InputStream getInputStream() throws Exception{
File file = new File("xxx");
return new FileInputStream(file);
}
}
相应的struts.xml配置为:
<package name="hello" extends="struts-default">
<action name="donwAction" class="xxx">
<result type="stream"> </result>
</action>
</package>
防止表单的重复提交:
表单重复即用户在页面多次点击提交按钮,或者通过不断刷新页面,把已经提交过的数据多次向后台提交。struts2提供了<s:token/>标签来防止重复提交,Token也被称作令牌。
<s:token/>标签的使用非常简单,只需要提交页面的<s:form>标签内加上字标签<s:token/>即可。当进行重复提交时,会引用重复提交时的错误信息,重复提交的错误信息以动作错误信息的方式存在,所以只要使用<s:actionerror/>标签引用即可。
<body>
<%@ taglib prefix="s" uri="/struts-tags"%>
<s:actionerror/>
<s:from action="/xxx.action" method="post">
<s:token/>
<s:textfield name="id" label="id"/>
<s:submit value="submit"/>
</body>
使用<s:token/>标签,必须为Action引用token的预定义***,它不在defaulttack***栈中,需要手动的引用token***。如果有重复提交的行为,struts2将跳转到这个Action定义的名为invalid.token的Result,对应的struts.xml:
<package name="hello" extends="struts-default">
<action name="tokenAction" class="xxx">
<interceptor-ref name="token"/>
<interceptor-ref name="defaultStack"/>
<result>xxx.jsp</result>
<result name="invalid.token">xxx.jsp</result>
</action>
</package>
<s:token/>原理:
<stoken/>标签在页面初始化的时候,向session中写入一个名为struts.token的属性,其值是一个随机数,然后再表单中生成两个隐藏域:struts.token.name域来记录session中写入属性的名字,sturts.token域记录了session的struts.token值一样的随机数。
token***在请求提交的时候,在Action运行之前,比较session的struts.token属性和表单的struts.token隐藏域中的值,如果相等,则移除session的struts.token属性,然后执行execute方法,如果不相等,则重定向到名为invalid.token的结果。
参考《研磨Struts2》 建议亲自阅读此书,加深理解,以上笔记只包含部分内容,如想全面了解,可以阅读此书。