fileupload渗透分析(org.apache.commons.fileupload渗透分析)

本文详细介绍了如何使用Apache Commons FileUpload组件实现文件上传功能。包括配置上传限制、处理上传过程中的临时文件、解析请求中的文件数据等内容。
fileupload渗透分析(org.apache.commons.fileupload渗透分析)

 

 

 

 

package com.zy.service;   
  
import java.io.File;   
import java.io.IOException;   
import java.io.PrintWriter;   
import java.util.Iterator;   
import java.util.List;   
  
import javax.servlet.ServletException;   
import javax.servlet.http.HttpServlet;   
import javax.servlet.http.HttpServletRequest;   
import javax.servlet.http.HttpServletResponse;   
  
import org.apache.commons.fileupload.FileItem;   
import org.apache.commons.fileupload.FileUploadException;   
import org.apache.commons.fileupload.disk.DiskFileItemFactory;   
import org.apache.commons.fileupload.servlet.ServletFileUpload;   
  
public class UpFileProcessServlet extends HttpServlet {   
  
public void doGet(HttpServletRequest request, HttpServletResponse response)   
    throws ServletException, IOException {   
  
   response.setContentType("text/html");   
   request.setCharacterEncoding("utf-8");   
   this.FileUpCenter(request, response);//调用文件上传中心类   
          
           
      }   
        
     /*文件上传中心类*/  
        private void FileUpCenter(HttpServletRequest request,HttpServletResponse response){   
           /*  
            * 1.处理文件 上传 首先要 创建ServletFileUpload类的实例  
            * */  
            ServletFileUpload upload=new ServletFileUpload();   
            /*  
             * 2.设置整个请求最大值,默认为-1(表示没有上限)  
             * */  
            upload.setSizeMax(-1);   
            /*  
             * 3.设置单个文件的大小 10M 默认为-1(没有上限)  
             * */  
            upload.setFileSizeMax(1024*1024*10);   
            /*  
             * 4.设置上传的临时数据(某一个数据在上传中被保存的数据) 在内存中 的大小  
             * */  
                    //1.创建[文件项目]的工厂_友情提示:如果用DiskFileUpload处理文件上传 可不用创建该工厂          
                      DiskFileItemFactory diskFileItemFactory=new DiskFileItemFactory();   
                   //2.设置 内存缓存 默认为(10240)10k 咱们设置为5K   
                       diskFileItemFactory.setSizeThreshold(1024*5);   
                    //3.设置超过缓存部分的 数据 存储目录 该目录默认为:C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\   
                        //咱们设置为当前应用上下文的/upload/temp路径   
                           diskFileItemFactory.setRepository(new File( this.getServletContext().getRealPath("/upload/temp")));   
                       //4.把改工厂设置到upload使其具有以上属性   
                           upload.setFileItemFactory(diskFileItemFactory);   
                /*  
                 * 5.设置监听器 用于监听文件的上传情况(方便结合ajax与进度条 的使用)  
                 * */          
                           //如:upload.setProgressListener(pListener);   
                /*  
                 * 6.解析数据 解析请求中的数据 (主要是创建FileItem)  
                 * */    
                       List fileItems=null;      
                    try {   
                 fileItems=upload.parseRequest(request);   
       /*分析:该方法首先创建了ServletRequestContext的实例  
       *       然后从请求对象中获取了 字符集|编码|请求的总大小|输出流  
       *       然后创建了其内部类FileItemIteratorImpl,  
       *          该类负责检查字符集是否合法|请求总大小是否大于自定义的总大小,  
       *          如果超过会抛一个SizeLimitExceededException异常 等  
       *          这个内部类的主要作用就是对文件数据的一些判断 如name名称 等   
       *       然后经过一些复杂的周折,它会通过请求总大小,nam属性名称,文件名,和是否是file类型来创建FileItem的示例以及通过Streams的copy方法来传递一些输入输出流  
       * */  
        } catch (FileUploadException e) {   
       e.printStackTrace();   
        }   
       /*  
        * 7.一切准备工作做好了,咱们就开始处理每个表单的单个字段(当然如果你就上传一个文件 只有一个表单可以处理 呵呵)  
        * */  
         //1.首先创建一个迭代器Iterator i = fileItems.iterator();   
        Iterator i = fileItems.iterator();   
       //2.迭代 取出每一个FileItem进行分析   
        while (i.hasNext())    
            {   
                FileItem fi = (FileItem) i.next();   
                //3.isFormField方法用于判断FileItem类对象封装的数据是否属于一个普通表单字段,还是属于一个文件表单字段,如果是普通表单字段则返回true,否则返回false。   
                if (!fi.isFormField())//取反    
                {   
                        try    
                        {   
                      //4.通过getName()方法取表单中name属性对应的文件名   
                               //注:只要表单中只要设置了name属性,即便没有上传任何东西 该表单仍然对应一个FileItem对象 只是name为空。所以要对getName() 的值进行非空判断   
                          String pathThatSrc = fi.getName();   
                          if(pathThatSrc.trim().equals(""))   
                          {   
                              continue;   
                          }   
                          int start = pathThatSrc.lastIndexOf(File.separator);//通过"\\"截取索引的下标位置   
                          String fileName = pathThatSrc.substring(start + 1);//把下标位置+1的下标开始截取文件名(再补充一下昂,如果你上传的是中文文件名的文件 最后传到服务器上会变成乱码 也许要修改源码才可以解决)推荐 使用 UUID 来作为文件名称     
                          File bulidFile = new File(this.getServletContext().getRealPath("/upload/filedir"), fileName);//通过目录 和 文件名 创建File对象 你还可以对该File进行存在与否的判断       
                         //5.写入文件   
                          fi.write(bulidFile);   
                          String fieldName = fi.getFieldName();   
                          request.setAttribute(fieldName, fileName);   
                        }   
                     catch (Exception e)    
                     {   
                             e.printStackTrace();   
                             return;   
                     }   
                     finally  
                     {   
                         fi.delete();//无论是否出现异常 都要去清理临时 文件夹 里的数据   
                     }   
         
                }//if end   
  
            }//while end   
  
        }//class end   
  
  
  
public void doPost(HttpServletRequest request, HttpServletResponse response)   
    throws ServletException, IOException {   
             this.doGet(request, response);   
}   
  
}  

 

 

 

原文地址:http://celerity.iteye.com/blog/295528

<think>嗯,用户遇到了Java中的类型转换错误,具体是FileItemInputIteratorImpl无法转换为FileItemIterator。这个问题发生在Spring Boot应用中使用Tomcat和commons-fileupload库的时候。我需要仔细分析可能的原因和解决方案。 首先,我应该考虑依赖版本的问题。Spring Boot可能已经集成了某些库的不同版本,导致冲突。用户可能同时引入了不同版本的commons-fileuploadcommons-io,这会引起类路径中的不一致。例如,FileItemInputIteratorImpl可能在某个版本中实现了FileItemIterator接口,但另一个版本可能结构不同,导致转换异常。 接下来,检查类加载机制。Tomcat使用自己的类加载器,可能在部署时导致类加载问题,特别是当应用和服务器依赖的库版本不一致时。这时候需要确认依赖的作用域是否正确,比如是否将commons-fileupload标记为provided,或者是否需要排除某些传递依赖。 然后,查看代码中的显式转换部分。用户可能在代码中直接将某个对象强制转换为FileItemIterator,但如果实际返回的是不兼容的实现类,就会抛出ClassCastException。这时候需要检查创建该对象的部分,确保使用的是正确的工厂方法,比如ServletFileUpload类的getItemIterator方法,而不是直接实例化某个实现类。 另外,Spring Boot的自动配置可能影响了文件上传的处理方式。如果用户同时使用了Spring MVC的多部分解析器和commons-fileupload,可能会导致冲突。需要确认是否正确地配置了MultipartResolver,并确保只使用一种文件上传处理方式。 可能还需要检查Maven或Gradle的依赖树,查看是否有版本冲突。使用Maven的dependency:tree命令可以帮助识别重复或冲突的依赖。如果有多个版本的commons-fileupload存在,需要排除掉不需要的版本,确保统一使用兼容的版本。 最后,建议用户更新到最新的稳定版本,因为较新的版本可能已经修复了相关的兼容性问题。同时,提供一个简单的示例配置,帮助用户正确初始化FileItemIterator,避免直接类型转换的错误。</think>在Spring Boot应用中处理文件上传时遇到$FileItemInputIteratorImpl$无法转换为$FileItemIterator$的类型转换错误,通常由以下原因和解决方案构成: ### 一、依赖冲突分析 1. **版本不匹配**:检查$commons-fileupload$与$commons-io$的版本 ```xml <!-- 推荐使用最新稳定版本 --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.5</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.11.0</version> </dependency> ``` 2. **类加载器问题**:Tomcat可能导致不同模块加载不同版本的类[^1] ```bash # 使用Maven检查依赖树 mvn dependency:tree -Dincludes=commons-fileupload ``` ### 二、代码修正方案 ```java // 正确的初始化方式(避免直接类型转换) ServletFileUpload upload = new ServletFileUpload(); FileItemIterator iter = upload.getItemIterator(request); // 使用标准接口方法 ``` ### 三、Spring Boot配置优化 1. **禁用默认配置**(当同时存在多个文件处理器时) ```properties spring.servlet.multipart.enabled=false ``` 2. **显式声明Bean** ```java @Bean(name = "multipartResolver") public CommonsMultipartResolver multipartResolver() { CommonsMultipartResolver resolver = new CommonsMultipartResolver(); resolver.setMaxUploadSize(10485760); return resolver; } ``` ### 四、Tomcat特殊处理 检查$context.xml$中是否包含冲突配置: ```xml <!-- 避免在Tomcat级别配置上传处理器 --> <Context> <Manager className="org.apache.catalina.session.StandardManager" /> </Context> ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值