Struts2文件上传(二) 深入FileUploadInterceptor
副标题#e#
Struts2框架自己没有文件上传的成果模块,而是操作此刻风行的几个文件上传开源框架,如Common -FileUpload和COS等。 Struts2操作拦截器将这些文件上传的框架巧妙的集成进来,不能不被称为一个 优秀的拿来主义者。由于拦截器的利用,我们利用Struts2实现文件上传变的很是容易,好像什么也没产生,文件已经上传随处事器了,但假如仅仅是利用这个成果,大概永远不知道Struts2为你做了几多工作 。最近有点闲,阐明白下下Struts2源码,才弄清楚个中的真相,条记一下,以免遗忘。
Struts2操作request理会器来集成其他的文件上传框架,Struts2提供了默认的request理会器 JakartaMultiPartRequest,在default.properties的struts.multipart.parser参数就是设置request解 析器,默认为jakarta也就是JakartaMultiPartRequest。虽然,你也可以配置成cos,不外Struts2 没有 提供适配cos的request理会器,你得本身实现,然后设置到本身的应用。JakartaMultiPartRequest也就 是操作 Common-FileUpload来对request举办理会,然后生存理会功效。详细事情就是操作Common- FileUpload的 ServletFileUpload对request举办理会,获得所有的FileItem的list,然后对这个list进 行阐明。假如是文件上传表单,则以表单的name属性分组,以表单name属性为key,对应的FileItem列表 为Value生存到一个Map中。JakartaMultiPartRequest的事情已经完成,虽然,这个Map中生存的所有的 FileItem,框架已经将文件生存到一个姑且目次里了,这个姑且目次你也可以设置,参数为struts.multipart.saveDir,还要设置一个文件上传总巨细,参数为 struts.multipart.maxSize。
接着就是FileUploadInterceptor的事情了,他的事情也很是简朴。首先举办验证,如文件上传 巨细限制,上传范例限制验证等。然后以表单名来结构三个参数,譬喻:你的文件上传表单name为 upload,则这三个参数为:upload,uploadContentType,uploadFileName。然后生存到ActionContext的 PARAMETERS 中,虽然假如表单许多,并且表单名又差异,他就会发生差异表单名对应的参数。最后系统 的ParametersInterceptor拦截器会将 ActionContext的getParameters()获得的各个参数映射赋值给 Action的各个属性,这就是为什么我们在开拓文件上传的时候必然要在Action中提供与表单名沟通的 File工具(假如一个表单名又多个上传文件,这是可以是File数组或是File的List),文件名 +ContentType,和文件名+FileName 这三种参数。
框架为我们所做的就是这些了,剩下的就是文 件拷贝了。此刻我们来留意下Action的这几个参数,个中File工具(虽然也大概是数组或List),这时他 们已经指向系统姑且目次里的某个文件,或是系统的内存里的数据了。在我们传输数据时,实际上是从 这个姑且文件或内存将数据库拷贝到上传目次里去的,当执行完Action之后,FileUploadInterceptor会 将姑且目次里所有姑且文件删除,这也是为什么上传文件完成后会有一些日志显示说删除了一些姑且文 件的原因。
此刻实现一个简朴的文件上传,首先熟悉下几个参数设置:
1.struts.multipart.parser 设置request理会器,Struts2默认为jakarta 也就是 JakartaMultiPartRequest,我们也 可以本身开拓本身的理会器。
2.struts.multipart.saveDir 上传文件的姑且生存目次,我们知道Common-FileUpload需要提供一个姑且目次的。假如没有配置, 则是 ServletContext.getAttribute("javax.servlet.context.tempdir")对应的目次,对应于 Common- FileUpoad中的repository参数。
3.struts.multipart.maxSize 这个是设置文件上传总巨细,单 位为B,默认巨细为2097152b,对应于Common-FileUpload中的sizeMax参数。
在设置 FileUploadInterceptor时候也有几个参数:
1.maximumSize 这是配置答允上传的单个文件的 巨细,假如某个文件巨细大于这个巨细,则会发生一个错误生存到Action中,错误的i18n的key为 struts.messages.error.file.too.large
2.allowedTypesSet 这是配置答允上传文件的范例,多 个范例以逗号“,”离隔,假如某个文件的范例没在这个配置之类,则会发生一个错误生存 到Action中,错误的i18n的的key为 struts.messages.error.content.type.not.allowed
3.allowedExtensionsSet这是配置答允上传 文件的后缀,多个范例以逗号“,”离隔,假如某个文件的后缀没在这个配置之类,则会产 生一个错误生存到Action中,错误的i18n的的key为 struts.messages.error.file.extension.not.allowed
struts.xml设置示例:
Xml代码
<struts>
//设置文件生存的姑且目次
<constant name="struts.multipart.saveDir" value="C:\Documents and Settings\bond\My Documents\temp"></constant>
//设置上传总巨细
<constant name="struts.multipart.maxSize" value="1024102400"></constant>
<package name="strutsDemo" extends="struts-default">
<action name="Upload" method="upload" class="com.bond.action.LoginAction">
//文件上传的保 存目次
<param name="savePath">/upload</param>
<result name="success">/success.jsp</result>
<result name="error">/failure.jsp</result>
<interceptor-ref name="fileUpload">
//单个文件答允的巨细
<param name="maxinumSize">10240000000</param>
//答允上传的文件范例,可以到% Tomcat_home%/conf下的web.xml文件中找到所有文件范例的范例名
<param name="allowedTypesSet">application/zip,application/pdf,image/gif</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
</package>
</struts>
#p#分页标题#e#
这里我们设置了fileUpload拦截器,我们还 必需吧dufaultStack加上,由于defaultStack中已经包括了fileUpload拦截器,所以fileUpload拦截器 会执行俩遍,所以我们会在日志信息中看到俩次排除姑且文件的记录。
#p#副标题#e#
UploadAction:
Java代码
public class UploadAction extends ActionSupport {
// 必需的参数,参数名与表单名沟通,假如一个表单名对应多个上传文件,
//则必需为数组或 List
private File[] upload;
//必需的参数,名目:表单名+ContentType,暗示上传文 件范例
private String[] uploadContentType;
//必需的参数,名目:表单名+FileName ,暗示上传的文件名
private String[] uploadFileName;
//文件生存目次
private String savePath;
public LoginAction() {
}
public String upload() throws Exception {
for (int i=0;i<getUpload().length;i++) {
FileInputStream in = new FileInputStream(getUpload()[i]);
FileOutputStream out = new FileOutputStream(getSavePath()+"\\"+getUploadFileName()[i]);
//将数据拷贝到 上传目次,这里没有须要利用缓冲流,因为IOUtils东西类已经利用了缓存
IOUtils.copy(in, out);
}
return SUCCESS;
}
。。。。。。get/set要领。。。。
页面表单示例:
Html代码
<!-- method必然要为post, enctype必然要为 multipart/form-data,表单名必然要和Action中的参数名沟通-->
<s:form method="post" id="loginForm" action="Upload"
enctype="multipart/form- data">
<table style="border: 1px solid;" align="center">
<thead>
<tr>
<td style="text-align: center" colspan="2">文 件上传</td>
</tr>
</thead>
<tbody>
<tr>
<td>用户名:</td>
<td><input type="text" name="username"></input></td>
</tr>
<tr>
<td>暗码:</td>
<td><input type="text" name="password"></input></td>
</tr>
<tr>
<td colspan="2"><input type="file" name="upload" /></td>
</tr>
<tr>
<td colspan="2"><input type="file" name="upload" /></td>
</tr>
<tr>
<td colspan="2"><input type="file" name="upload" /></td>
</tr>
<tr>
<td><input type="button" value="Upload" id="upload" /></td>
<td><input type="button" value="Cancel" id="cancelUpload" /></td>
</tr>
</tbody>
</table>
这样,一个简朴的文件上传就实现了,可是感受文件上传无声无息, 出格上传大文件,等了很长时间才知道有没有上传乐成,要是有上传进度条能实时显示上传进度,这样 的文件上传的成果才气算完善了,上传进度条的成果下篇再写。