Java使用Commons-FileUpload组件实现文件上传最佳方案

Posted jimisun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java使用Commons-FileUpload组件实现文件上传最佳方案相关的知识,希望对你有一定的参考价值。

学习的目标
使用commons-fileupload实现文件上传
使用commons-fileupload封装文件上传工具类
 
什么是commons-fileupload?
The CommonsFileUploadpackage makes it easy to add robust, high-performance, file upload capability to your servlets and web applications.
FileUpload parses HTTP requests which conform toRFC 1867, "Form-based File Upload in html". That is, if an HTTP request is submitted using the POST method, and with a content type of "multipart/form-data", then FileUpload can parse that request, and make the results available in a manner easily used by the caller.
 
FileUpload包可以很容易地添加强大的,高性能,文件上传到你的Servlet的Web应用程序的能力。
FileUpload解析HTTP请求符合RFC 1867年,“在HTML的文件上传。就是说,如果一个HTTP请求是使用POST方法提交,并与一个内容类型“multipart/form-data”,然后FileUpload可以解析这个请求,并把结果提供一个容易使用的调用方式。
 
为什么要使用commons-fileupload
在使用传统的Servlet上传的时候我们可以使用req.getInputStream()来获取文件上传的流,我们在获取到这个流之后需要手动的针对这个流进行特殊处理进行去流中不必要的开始和结束内容,才能真正的获取到流的内容,本章节并不对原始Servlet的上传进行探究,我们另开章节针对原始Servelt上传进行探究。
 
使用commons-fileupload的要求
  1. method方法必须是POST,不能是GET
  2. 新加一个属性enctype,值为”multipart/form-data”
  3. 文件表单项<input>的类型为file,即type=”file”
commons-fileupload的Maven依赖 
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

 

使用commons-fileupload核心步骤解读
第一步:判断是否可以进行文件上传
第二步:创建一个FileItem工厂,通过工厂创建文件上传核心组件ServletFileUpload对象
第三步:通过核心上传组件解析request请求,获取表单的所有表单项,表单的每一个表单项对应一个FileItem
 
第四步:遍历所有的表单项,判断是否是普通的表单项,如果不是就是文件上传,就可以针对遍历的这个fileItem进行一系列的操作
封装一个工具类,让我们在处理文件上传的时候爽呀爽
在上面我们已经介绍过了使用commons-fileupload上传文件的整个流程,所以我们就直接将这个流程封装成一个工具类,在使用到文件上传的Servlet中直接使用,十分便利
第一步:创建一个DTO(用于存储commons-fileupload解析请求的结果) 
import org.apache.commons.fileupload.FileItem;
 
import java.util.HashMap;
import java.util.Map;
 
public class ParamDto {
 
    private Map<String,String> paramMap;
    private Map<String,FileItem> fileMap;
 
    public ParamDto() {
        paramMap = new HashMap<>();
        fileMap = new HashMap<>();
    }
 
    public Map<String, String> getParamMap() {
        return paramMap;
    }
 
    public void setParamMap(Map<String, String> paramMap) {
        this.paramMap = paramMap;
    }
 
    public Map<String, FileItem> getFileMap() {
        return fileMap;
    }
 
    public void setFileMap(Map<String, FileItem> fileMap) {
        this.fileMap = fileMap;
    }
}

 

第二步:将commons-fileupload解析文件的整个请求,封装成一个工具类
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;
import org.imooc.dto.ParamDto;
 
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.List;
 
public class RequestUtil {
 
    /**
     * 从request流中解析参数与上传的文件
     * @param request
     */
    public static ParamDto parseParam(HttpServletRequest request) {
 
        ParamDto result = new ParamDto();
 
//创建一个FileItem工厂 通过DiskFileItemFactory对象创建文件上传核心组件
        ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
        upload.setHeaderEncoding("UTF-8");
 
        try {
//通过文件上传核心组件解析request请求,获取到所有的FileItem对象
            List<FileItem> fileItemList = upload.parseRequest(request);
 
//遍历表单的所有表单项(FileItem) 并对其进行相关操作
            for(FileItem fileItem : fileItemList) {
//判断这个表单项如果是一个普通的表单项
                if(fileItem.isFormField()) {
                    result.getParamMap().put(fileItem.getFieldName(),fileItem.getString("UTF-8"));
//如果不是表单的普通文本域,就是
                } else {
                    result.getFileMap().put(fileItem.getFieldName(),fileItem);
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}

 

第三步:让我们直接在Servlet中使用这个工具类吧,哈哈
 
另:我们当然可以封装一个保存文件(Item)的一个通用方法
import org.apache.commons.fileupload.FileItem;
 
import java.io.File;
 
public class FileUtil {
 
    /**
     * 上传文件的保存路径
     */
    public static final String SAVE_PATH = "d:/upload/";
 
    /**
     * 保存上传的文件
     * @param fileItem
     * @param path
     * @return
     * @throws Exception
     */
    public static String save(FileItem fileItem,String path) throws Exception {
        String fileName = System.currentTimeMillis() + "_" + fileItem.getName();
        fileItem.write(new File(path + fileName));
        return fileName;
    }
}

 

好啦~ 有空我们再来看看原始的文件上传方式

 

以上是关于Java使用Commons-FileUpload组件实现文件上传最佳方案的主要内容,如果未能解决你的问题,请参考以下文章

Java文件上传大杀器-绕waf(针对commons-fileupload组件)

Java文件上传大杀器-绕waf(针对commons-fileupload组件)

Java文件上传大杀器-绕waf(针对commons-fileupload组件)

commons-fileupload处理plupload多文件上传

commons-fileupload上传文件

文件上传之 commons-fileupload