FileUpload--ServletFileUpload.parseRequest()在springboot中使用出现的问题

直接上代码,代码中注释(代码出处https://www.cnblogs.com/liuyangv/p/8298997.html)
java 中的注释写的非常详细



先说下这段代码中出现的错误,js代码 后附上
1.
String realPath = this.getServletContext().getRealPath("/upload");报错this.getServletContext()
更改为:
request.getSession().getServletContext().getRealPath("/upload");

2.
List items =upload.parseRequest(req); 报错upload.parseRequest
更改为:
List items = upload.parseRequest(new ServletRequestContext(request));
3.
List items获取到空list
其中FileItemIterator iter = upload.getItemIterator(request);这段获取的是空值。
(引自:https://blog.csdn.net/zhou_pp/article/details/85060076)
问题的原因是:

spring-boot自带的org.springframework.web.multipart.MultipartFile
和Multipart产生冲突,如果同时使用了MultipartResolver 和ServletFileUpload,就会在iter.hasNext()返回false.然后整个循环就跳出去了。整个问题产生的原因是Spring框架先调用了MultipartResolver 来处理http multi-part的请求。这里http multipart的请求已经消耗掉。后面又交给ServletFileUpload ,那么ServletFileUpload 就获取不到相应的multi-part请求。因此将multipartResolve配置去除,问题就解决了。

在使用ServletFileUpload时需要关闭Spring Boot的默认配置 ,所以在配置文件中添加

spring.http.multipart.enabled=false 

获取的是空值是最大的问题, 总结问题有
网上搜索该问题的解决方法,大致有以下两种:
(1)原因在于Spring的配置文件中已经配置了MultipartResolver,导致文件上传请求已经被预处理过了,所以此处解析文件列表为空,对应的做法是删除该段配置。
(2)认为是structs的过滤器导致请求已被预处理,所以也要修改对应过滤器的配置。
然而,在SpringBoot下,上述两种解决方法不可能做到,因为SpringBoot的相关配置都是自己完成的,根本没有显示的配置文件。况且以上两种解决方法,修改配置文件可能影响整个工程的其他部分,所以得另寻方案.

package cn.gs.ly;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
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.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;


public class FileUploadServlet extends HttpServlet {
    @Override
    protected void  ****(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
        //得到上传文件的保存目录。 将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
        String realPath = this.getServletContext().getRealPath("/upload");//  /WEB-INF/files
        System.out.println("文件存放位置:"+realPath);
        //设置临时目录。 上传文件大于缓冲区则先放于临时目录中
        String tempPath = "E:\\tempPath";
        System.out.println("临时文件存放位置:"+tempPath);
        
        
        //判断存放上传文件的目录是否存在(不存在则创建)
        File f = new File(realPath);
            if(!f.exists()&&!f.isDirectory()){
                System.out.println("目录或文件不存在! 创建目标目录。");
                f.mkdir();
            }
        //判断临时目录是否存在(不存在则创建)
        File f1 = new File(tempPath);
            if(!f1.isDirectory()){
                System.out.println("临时文件目录不存在! 创建临时文件目录");
                f1.mkdir();
            }
        
       /**
        * 使用Apache文件上传组件处理文件上传步骤:
        * 
        * */
        //1、设置环境:创建一个DiskFileItemFactory工厂    
        DiskFileItemFactory factory = new DiskFileItemFactory();
        
            //设置上传文件的临时目录
        factory.setRepository(f1); 
        
        //2、核心操作类:创建一个文件上传解析器。
        ServletFileUpload upload = new ServletFileUpload(factory);
            //解决上传"文件名"的中文乱码
        upload.setHeaderEncoding("UTF-8");
        
        //3、判断enctype:判断提交上来的数据是否是上传表单的数据
        if(!ServletFileUpload.isMultipartContent(req)){
            System.out.println("不是上传文件,终止");
             //按照传统方式获取数据
            return;
        }
        
        //==获取输入项==
//            //限制单个上传文件大小(5M)
//            upload.setFileSizeMax(1024*1024*4);
//            //限制总上传文件大小(10M)
//            upload.setSizeMax(1024*1024*6);
        
        //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List集合,每一个FileItem对应一个Form表单的输入项
            List items =upload.parseRequest(req);
            for(FileItem item:items){
                //如果fileitem中封装的是普通输入项的数据(输出名、值)
                if(item.isFormField()){
                    String filedName = item.getFieldName();//普通输入项数据的名
                    //解决普通输入项的数据的中文乱码问题
                    String filedValue = item.getString("UTF-8");//普通输入项的值
                    System.out.println("普通字段:"+filedName+"=="+filedValue);
                }else{
                    //如果fileitem中封装的是上传文件,得到上传的文件名称,        
                    String fileName = item.getName();//上传文件的名
                    //多个文件上传输入框有空 的 异常处理
                    if(fileName==null||"".equals(fileName.trim())){  //去空格是否为空
                        continue;// 为空,跳过当次循环,  第一个没输入则跳过可以继续输入第二个
                    }
                    
                    //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
                    //处理上传文件的文件名的路径,截取字符串只保留文件名部分。//截取留最后一个"\"之后,+1截取向右移一位("\a.txt"-->"a.txt")
                    fileName = fileName.substring(fileName.lastIndexOf("\\")+1);
                    //拼接上传路径。存放路径+上传的文件名
                    String filePath = realPath+"\\"+fileName;
                    //构建输入输出流
                    InputStream in = item.getInputStream(); //获取item中的上传文件的输入流 
                    OutputStream out = new FileOutputStream(filePath); //创建一个文件输出流
                    
                    //创建一个缓冲区
                    byte b[] = new byte[1024];
                    //判断输入流中的数据是否已经读完的标识
                    int len = -1;
                     //循环将输入流读入到缓冲区当中,(len=in.read(buffer))!=-1就表示in里面还有数据
                    while((len=in.read(b))!=-1){  //没数据了返回-1
                    //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath+"\\"+filename)当中
                        out.write(b, 0, len);
                    }
                    //关闭流
                    out.close();
                    in.close();
                    //删除临时文件
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    item.delete();//删除处理文件上传时生成的临时文件
                    System.out.println("文件上传成功");
                }    
            }    
        } catch (FileUploadException e) {
            //e.printStackTrace();
            throw new RuntimeException("服务器繁忙,文件上传失败");
        }    
    }

下面是js代码

<%@ page language="java" contentType="text/html" pageEncoding="utf-8"%>



文件上传


    
用户名:
文件1:
文件2:

有以下方法的介绍,非常详细

文件上传的前提
 1.form表单的method必须是post
 2.form表单的enctype必须是multipart/form-data 以二进制字节流
 进行提交 传统接收参数的方式无效
 DiskFileItemFactory:环境
     void setSizeThreshold(int sizeThreshold)
     设置缓冲区大小,默认10KB 超出将使用临时文件上传
     void setRepository(File repository)
     设置临时文件路径
 ServletFileUpload:核心操作类
     public void setSizeMax(long sizeMax)设置总文件的大小
     public void setFileSizeMax(long fileSizeMax):设置单个文件的大小
     public List parseRequest(javax.servlet.http.HttpServletRequest req)
     解析请求正文内容
     public static boolean isMultipartContent(HttpServletRequest req)//判断enctype
 FileItem:输入域
     boolean  isFormField():判断是否是普通字段
     String getName():获取上传文件名
     String getFieldName():获取普通字段的字段名
     String getString():获取普通字段的值
     String getContentType() 获得文件类型
     InputStream  getInputStream()以流的形式返回上传文件的主体内容
     void  delete()删除临时文件
 文件上传中需要注意的问题
    1.保证安全 
        上传文件放在WEB-INF目录中
    2.中文乱码问题
        普通字段乱码
        String fieldValue = item.getString("GBK");
          文件名乱码
          request.setCharacterEncoding("GBK");
      3.重名文件覆盖
          1.UUID
          2.使用文件上传日期分类存储
          3.System.currentMillions()
      4.限制文件上传类型
         1.endsWith("")这种方式不可取
         2.判断其mime类型 getContentType()
      5.限制用户上传文件的大小
          1.限制单个上传文件的大小
          upload.setFileSizeMax(4*1024*1024);
          2.限制总文件大小
        upload.setSizeMax()
     6.临时文件
         item.delete();
     7.多个文件上传时,没有上传内容的问题
         if(fileName==null||"".equals(fileName.trim())){
                        continue;
        }
     8.上传进度检测
            upload.setProgressListener(new ProgressListener(){
                参数一:已上传的字节数
                参数二:总字节数
                参数三:第几项
                @Override
                public void update(long arg0, long arg1, int arg2) {
                    // TODO Auto-generated method stub
                    System.out.println(arg0+"  "+arg1+"  "+arg2);
                }
                
            });

你可能感兴趣的:(FileUpload--ServletFileUpload.parseRequest()在springboot中使用出现的问题)