- 浏览: 117953 次
- 性别:
- 来自: 福建
文章分类
最新评论
-
wenbing2610:
其实用Struts实现图片上传比用Servlet实现容易多了。 ...
Struts2文件上传深入FileUploadInterceptor -
i_feng:
public class uploadImageAction ...
Struts2文件上传深入FileUploadInterceptor -
wenbing2610:
...
ognl.MethodFailedException
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配置示例:
- <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>
<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>
这里我们配置了fileUpload拦截器,我们还必须吧dufaultStack加上,由于defaultStack中已经包含了fileUpload拦截器,所以fileUpload拦截器会执行俩遍,所以我们会在日志信息中看到俩次清除临时文件的记录。
UploadAction:
- 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方法。。。。
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方法。。。。
页面表单示例:
- <!-- 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>
这样,一个简单的文件上传就实现了
评论
<!-- 允许上传文件大小默认为2097152字节(2M) -->
<param name="maximumSize">409600</param>
</interceptor-ref>。
/**
*
*/
private static final long serialVersionUID = 6335701337446433379L;
private String savePath;//struts.xml中已配置
HttpServletRequest request;
public String getSavePath() {
return ServletActionContext.getServletContext().getRealPath(savePath);
}
public void setSavePath(String savePath) {
this.savePath = savePath;
}
public void upload()
{
request=ServletActionContext.getRequest();
try {
System.out.println(request.getInputStream()+"..........");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
File temp = new File(System.getProperty("java.io.tmpdir"));//采用系统临时文件目录
File uploadPath = new File(getSavePath());
if (!uploadPath.exists()) {
uploadPath.mkdirs();
}
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
// diskFileItemFactory.setSizeThreshold(10*1024*1024); // 设置缓冲区大小
// diskFileItemFactory.setRepository(temp); //设置缓冲区目录
ServletFileUpload fu = new ServletFileUpload(diskFileItemFactory);
fu.setSizeMax(10*1024*1024);
List fileItems = fu.parseRequest(request);
我发现fileItems列表返回的值是空?不知道为什么??
if(fileItems.isEmpty()){
}
Iterator i = fileItems.iterator();
while (i.hasNext()) {
FileItem fi = (FileItem)i.next();
String fileName = fi.getName();
System.out.println(fileName+".....hasnext.....");
if (fileName != null) {
File fullFile = new File(fi.getName());
System.out.println("filename is null");
File savedFile = new File(getSavePath(), fullFile.getName());
fi.write(savedFile);
}
}
System.out.println("upload succeed");
} catch (Exception e) {
e.printStackTrace();
}
}
这个方法是用servlet可以获得从ios上传的图片,但是使用struts却实现不了,有些知识缺陷,不知道该怎么在struts里面实现,不知道你有没有什么好的方法?麻烦你了,谢谢!!使用它的缘故吗,还是配置问题request=ServletActionContext.getRequest();
发表评论
-
CSS样式表的overflow属性
2015-01-02 19:22 28一、滚动条样式overflow ... -
jrebel运用
2014-07-13 22:00 1187JRebel热部署 ... -
JPA执行原生SQL截断Char类型问题
2014-05-24 21:39 1185在JPA的API中执行原生 ... -
JPA基本数据类型映射
2014-05-24 21:06 3901/** ... -
spring定时器配置
2014-03-18 21:36 690创建测试类: ... -
The Struts dispatcher cannot be found
2013-11-03 18:48 650运行环境:struts2环境中访 ... -
JasperException
2013-09-15 20:41 1014JasperException异常: ... -
equal symbol expected
2013-09-15 20:08 1180equal symbol ... -
Hibernate主键生成器
2013-09-12 21:11 787... -
Criterion和Criteria
2013-09-08 16:00 1943Hibernate Criter ... -
getHibernateTemplate用法
2013-09-08 15:02 581HibernateTemplate提供的方法 ... -
JS中页面跳转
2013-09-08 14:01 652<html><head><t ... -
GridPanel详解
2013-03-10 10:45 10341、Ext.grid.GridPanel ... -
tomcat内存溢出
2013-03-04 20:26 723在使用Java程序从数据库中查询大量的数据或 ... -
History Object
2013-01-07 21:06 750history 对象是window 对象的另一个子 ... -
Write to programmer
2012-12-29 20:16 853很多的java初级程序员对自己没有一个明确的方 ... -
EL语言
2012-09-27 22:08 891EL的前世今生: ... -
JSTL标签的使用
2012-09-27 22:00 807JSP 标准标记库( Standard Tag Library ... -
使用IBATIS防止sql注入
2012-08-26 21:17 1599对于ibaits参数引用可以使用#和$两 ... -
IBATIS动态SQL标签用法
2012-08-26 21:04 12471、动态SQL片段通过SQL片 ...
相关推荐
本文将深入探讨Struts2中的FileUploadInterceptor,这是一个专门用于处理文件上传的拦截器。 首先,我们要理解Struts2拦截器的工作原理。拦截器是在Action执行前后插入的逻辑处理单元,它可以用来做一些预处理或后...
在本文中,我们将深入探讨如何使用Servlet来理解Struts2中的文件上传原理。Servlet是Java Web应用程序中的一个组件,用于处理HTTP请求和响应。而Struts2是一个基于MVC(模型-视图-控制器)设计模式的开源Web应用框架...
在本篇文章中,我们将深入探讨Struts2中文件上传的工作原理、实现方法以及相关注意事项。 首先,我们来看一下Struts2文件上传的基本流程: 1. 用户通过HTML表单选择本地文件,并提交到服务器。 2. Struts2拦截器...
在处理用户交互,特别是文件上传时,Struts2提供了一种便捷的方式。然而,文件上传功能也涉及到一个重要的问题,那就是大小限制。在实际应用中,为了防止恶意用户上传大文件导致服务器资源耗尽,或者保护服务器免受...
对于深入理解Struts2文件上传的工作原理,阅读源码是非常有帮助的。了解`FileUploadInterceptor`如何工作,以及`MultipartRequest`类如何解析Multipart请求,可以加深对整个过程的理解。 10. **实例实践** 博文...
2. **配置Action**:在Struts2的Action类中,需要创建一个字段与上传文件对应,通常使用`org.apache.struts2.interceptor.FileUploadInterceptor`拦截器处理文件上传。你需要在`struts.xml`配置文件中包含这个拦截器...
Struts2是一个流行的Java web框架,它为开发者提供了一种模型-视图-控制器(MVC)架构,便于构建可维护、可扩展的Web应用程序。文件上传是许多Web应用...这对于我们深入理解Struts2框架和优化文件上传功能非常有帮助。
在这个场景中,我们将深入探讨Struts2如何实现文件上传,以及涉及到的关键知识点。 首先,我们需要了解Struts2的配置。在Struts2中,我们通常会在struts.xml配置文件中定义一个Action,这个Action将处理文件上传...
在这个"Struts2文件上传教程"中,我们将深入探讨如何在Struts2环境中实现文件上传功能。 文件上传在web应用中很常见,例如用户可能需要上传头像、提交文档或分享图片。在Struts2中,这个过程涉及到几个关键组件和...
下面我们将深入探讨Struts2文件上传的相关知识点。 1. **Struts2配置**: 在Struts2中进行文件上传,首先需要在struts.xml配置文件中启用上传插件。添加以下配置以启用`struts2-convention-plugin`和`struts2-file...
Struts2 提供的 `org.apache.struts2.interceptor.FileUploadInterceptor` 拦截器和 `org.apache.struts2.components.File` 组件使得文件上传变得简单。同时,可以结合其他工具或库,如Apache Commons FileUpload,...
在本篇文章中,我们将深入探讨如何利用Struts2实现批量文件上传,以及涉及的相关技术与最佳实践。 首先,我们需要了解Struts2的核心概念——`Interceptor(拦截器)`,这是Struts2处理请求的核心组件,用于在Action...
Struts2是一个强大的Java web框架,它为开发者提供了丰富的功能,包括文件上传和下载。在Struts2中处理文件上传和下载是常见的需求,尤其是在构建交互式的Web应用时。在这个主题下,我们将深入探讨如何使用Struts2...
本篇将深入讲解如何使用Struts2实现文件上传,并提供一个简单的Demo示例。 首先,我们需要了解Struts2文件上传的核心组件——`FileUploadInterceptor`拦截器。这个拦截器负责处理上传请求中的文件内容。在Struts2的...