`

Struts2文件上传深入FileUploadInterceptor

阅读更多

         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代码 复制代码 收藏代码
  1. <struts>  
  2.          //配置文件保存的临时目录   
  3.     <constant name="struts.multipart.saveDir" value="C:\Documents and Settings\bond\My Documents\temp"></constant>  
  4.        
  5.         //配置上传总大小   
  6.         <constant name="struts.multipart.maxSize" value="1024102400"></constant>  
  7.        
  8.     <package name="strutsDemo" extends="struts-default">  
  9.        
  10.         <action name="Upload" method="upload" class="com.bond.action.LoginAction">  
  11.         //文件上传的保存目录   
  12.                 <param name="savePath">/upload</param>  
  13.             <result name="success">/success.jsp</result>  
  14.             <result name="error">/failure.jsp</result>  
  15.             <interceptor-ref name="fileUpload">  
  16.                                  //单个文件允许的大小   
  17.                 <param name="maxinumSize">10240000000</param>  
  18.                                  //允许上传的文件类型,可以到%Tomcat_home%/conf下的web.xml文件中找到所有文件类型的类型名   
  19.                 <param name="allowedTypesSet">application/zip,application/pdf,image/gif</param>  
  20.             </interceptor-ref>  
  21.             <interceptor-ref name="defaultStack"></interceptor-ref>  
  22.         </action>  
  23.     </package>  
  24. </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:

Java代码 复制代码 收藏代码
  1. public class UploadAction extends ActionSupport {   
  2.         //必须的参数,参数名与表单名相同,如果一个表单名对应多个上传文件,   
  3.         //则必须为数组或List   
  4.     private File[] upload;   
  5.         //必须的参数,格式:表单名+ContentType,表示上传文件类型   
  6.     private String[] uploadContentType;   
  7.         //必须的参数,格式:表单名+FileName,表示上传的文件名   
  8.     private String[] uploadFileName;   
  9.         //文件保存目录   
  10.     private String savePath;   
  11.   
  12.     public LoginAction() {   
  13.     }   
  14.   
  15.     public String upload() throws Exception {   
  16.         for (int i=0;i<getUpload().length;i++) {   
  17.             FileInputStream in = new FileInputStream(getUpload()[i]);   
  18.             FileOutputStream out = new FileOutputStream(getSavePath()+"\\"+getUploadFileName()[i]);   
  19.                        //将数据拷贝到上传目录,这里没有必要使用缓冲流,因为IOUtils工具类已经使用了缓存   
  20.             IOUtils.copy(in, out);   
  21.         }   
  22.         return SUCCESS;   
  23.     }   
  24. 。。。。。。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方法。。。。

 页面表单示例:

Html代码 复制代码 收藏代码
  1. <!-- method一定要为post,enctype一定要为 multipart/form-data,表单名一定要和Action中的参数名相同-->  
  2. <s:form method="post" id="loginForm" action="Upload"  
  3.     enctype="multipart/form-data">  
  4. <table style="border: 1px solid;" align="center">  
  5.     <thead>  
  6.         <tr>  
  7.             <td style="text-align: center" colspan="2">文件上传</td>  
  8.         </tr>  
  9.     </thead>  
  10.     <tbody>  
  11.         <tr>  
  12.             <td>用户名:</td>  
  13.             <td><input type="text" name="username"></input></td>  
  14.         </tr>  
  15.         <tr>  
  16.             <td>密码:</td>  
  17.             <td><input type="text" name="password"></input></td>  
  18.         </tr>  
  19.         <tr>  
  20.             <td colspan="2"><input type="file" name="upload" /></td>  
  21.         </tr>  
  22.         <tr>  
  23.             <td colspan="2"><input type="file" name="upload" /></td>  
  24.         </tr>  
  25.         <tr>  
  26.             <td colspan="2"><input type="file" name="upload" /></td>  
  27.         </tr>  
  28.         <tr>  
  29.             <td><input type="button" value="Upload" id="upload" /></td>  
  30.             <td><input type="button" value="Cancel" id="cancelUpload" /></td>  
  31.         </tr>  
  32.     </tbody>  
  33. </table>   

              这样,一个简单的文件上传就实现了

分享到:
评论
2 楼 wenbing2610 2012-11-24  
其实用Struts实现图片上传比用Servlet实现容易多了。在这里简要的说明几点:<1>在JSP页面使用Struts文件上传的标签<s:file name="xxx">会让你事半功倍!<2>在JSP页面提交的表单中加上:enctype="multipart/form-data" 表示文件提交的内容是二进制的,可以很好的处理提交的文件类型,特别注意form提交方法应该是method="post",也不能省去。<3>在要提交到的Action定义相应的变量,在Struts框架中是通过页面组件值通过name属性自动绑定到后台应用程序的相同名称的成员变量,但是在用Struts文件上传的时候,要遵循Struts的命名规范: 定义文件对象:File xxx,必须与file标签中的name属性值一样;文件名称:String xxxFileName,名称必须是file标签中的name属性值+FileName,同理,定义文件类型:String xxxContentType,此外还要提供get,set方法,因为底层把页面的值注入到后台应用程序是通过反射来实现的,在这里不详细说明。<4>如果要把上传的文件保存在数据库中:要设置上传文件大小的限制,例如:在Oracle数据库中Blob大对象类型最大存贮空间是2M,这可以通过在上传文件的Action配置文件中设置拦截器来实现:例如<interceptor-ref name="fileUpload">
<!-- 允许上传文件大小默认为2097152字节(2M) -->
<param name="maximumSize">409600</param>
</interceptor-ref>。
1 楼 i_feng 2012-10-31  
public class uploadImageAction extends ActionSupport{

/**
*
*/
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();

相关推荐

    Struts2文件上传(二) 深入FileUploadInterceptor

    本文将深入探讨Struts2中的FileUploadInterceptor,这是一个专门用于处理文件上传的拦截器。 首先,我们要理解Struts2拦截器的工作原理。拦截器是在Action执行前后插入的逻辑处理单元,它可以用来做一些预处理或后...

    通过Servlet文件上传理解Struts2文件上传原理(附源码)

    在本文中,我们将深入探讨如何使用Servlet来理解Struts2中的文件上传原理。Servlet是Java Web应用程序中的一个组件,用于处理HTTP请求和响应。而Struts2是一个基于MVC(模型-视图-控制器)设计模式的开源Web应用框架...

    struts2文件上传

    在本篇文章中,我们将深入探讨Struts2中文件上传的工作原理、实现方法以及相关注意事项。 首先,我们来看一下Struts2文件上传的基本流程: 1. 用户通过HTML表单选择本地文件,并提交到服务器。 2. Struts2拦截器...

    Struts2文件上传的大小限制问题

    在处理用户交互,特别是文件上传时,Struts2提供了一种便捷的方式。然而,文件上传功能也涉及到一个重要的问题,那就是大小限制。在实际应用中,为了防止恶意用户上传大文件导致服务器资源耗尽,或者保护服务器免受...

    Struts2.0文件上传原理

    对于深入理解Struts2文件上传的工作原理,阅读源码是非常有帮助的。了解`FileUploadInterceptor`如何工作,以及`MultipartRequest`类如何解析Multipart请求,可以加深对整个过程的理解。 10. **实例实践** 博文...

    struts2 文件的上传和下载

    2. **配置Action**:在Struts2的Action类中,需要创建一个字段与上传文件对应,通常使用`org.apache.struts2.interceptor.FileUploadInterceptor`拦截器处理文件上传。你需要在`struts.xml`配置文件中包含这个拦截器...

    struts2 文件上传源码

    Struts2是一个流行的Java web框架,它为开发者提供了一种模型-视图-控制器(MVC)架构,便于构建可维护、可扩展的Web应用程序。文件上传是许多Web应用...这对于我们深入理解Struts2框架和优化文件上传功能非常有帮助。

    Struts2文件上传

    在这个场景中,我们将深入探讨Struts2如何实现文件上传,以及涉及到的关键知识点。 首先,我们需要了解Struts2的配置。在Struts2中,我们通常会在struts.xml配置文件中定义一个Action,这个Action将处理文件上传...

    struts2 文件上传 教程

    在这个"Struts2文件上传教程"中,我们将深入探讨如何在Struts2环境中实现文件上传功能。 文件上传在web应用中很常见,例如用户可能需要上传头像、提交文档或分享图片。在Struts2中,这个过程涉及到几个关键组件和...

    struts2文件上传.

    下面我们将深入探讨Struts2文件上传的相关知识点。 1. **Struts2配置**: 在Struts2中进行文件上传,首先需要在struts.xml配置文件中启用上传插件。添加以下配置以启用`struts2-convention-plugin`和`struts2-file...

    struts2 文件上传

    Struts2 提供的 `org.apache.struts2.interceptor.FileUploadInterceptor` 拦截器和 `org.apache.struts2.components.File` 组件使得文件上传变得简单。同时,可以结合其他工具或库,如Apache Commons FileUpload,...

    Struts2批量上传文件

    在本篇文章中,我们将深入探讨如何利用Struts2实现批量文件上传,以及涉及的相关技术与最佳实践。 首先,我们需要了解Struts2的核心概念——`Interceptor(拦截器)`,这是Struts2处理请求的核心组件,用于在Action...

    Struts2文件上传下载

    Struts2是一个强大的Java web框架,它为开发者提供了丰富的功能,包括文件上传和下载。在Struts2中处理文件上传和下载是常见的需求,尤其是在构建交互式的Web应用时。在这个主题下,我们将深入探讨如何使用Struts2...

    java文件上传,Struts2文件上传,demo下载

    本篇将深入讲解如何使用Struts2实现文件上传,并提供一个简单的Demo示例。 首先,我们需要了解Struts2文件上传的核心组件——`FileUploadInterceptor`拦截器。这个拦截器负责处理上传请求中的文件内容。在Struts2的...

Global site tag (gtag.js) - Google Analytics