多文件上传你学废了吗?

需要的jar包

commons-fileupload-1.3.1.jar
commons-io-2.2.jar

导入了这两个包就可以用java进行文件上传了

文件上传的几大要素

  1. 上传的目标路径(就是要上传到服务器的那个目录)
  2. 需要有文件名 (有时需要生成随机id标识)
  3. 文件大小限制
  4. 文件类型限制
  5. 文件上传过程中的临时文件夹
  6. 文件上传过程中的内存缓存大小

我们可以将以上的几个属性封装成为类属性

	private static final String DEFAULT_TEMP_FILEPATH = "D:\\temp\\buffer\\";//默认临时路径

    private static final String[] DEFAULT_FILETYPE = {
    "jpg", "png", "bmp", "gif"};//默认上传的文件类型

    private static final int DEFAULT_SIZE_THRESHOLD = 1024 * 4;//默认缓存大小4k

    private static final int DEFAULT_SIZE_MAX = 1024 * 5000;//默认最大文件大小5mb

    private String fileLoadPath; //上传目标的路径

    private String fileName; //文件名

    private String tempFilePath; //临时文件夹

    private String[] fileType; //允许的文件类型

    private int sizeThreshold; //上传缓存区大小

    private int sizeMax; //上传文件最大大小限制

    private DiskFileItemFactory factory; //磁盘文件工厂

    private ServletFileUpload upload; //文件上传对象

前属性为默认值。

构建文件上传构造方法

我们进行文件上传是肯定要使用上面这个对象进行操作,那么我们得在这个对象实例化的时候做一些事情,比如初始化一些重要参数:

第一个构造方法:

/**
     * 自定义属性构造方法
     *
     * @param loadPath
     * @param tempFilePath
     * @param fileType
     * @param sizeThreshold
     * @param sizeMax
     */
    public FileLoadUtil(String loadPath, String tempFilePath, String[] fileType, int sizeThreshold, int sizeMax) {
    
        this.fileLoadPath = loadPath; //上传的目标路径
        this.tempFilePath = tempFilePath; //临时文件夹
        this.fileType = fileType; //指定文件类型
        this.sizeThreshold = sizeThreshold;  //缓存大小
        this.sizeMax = sizeMax; //文件最大允许大小
    }

第二个构造方法:

/**
     * 默认属性构造方法
     * @param loadPath
     */
    public FileLoadUtil(String loadPath) {
    
        this.tempFilePath = DEFAULT_TEMP_FILEPATH; //设置默认的临时路径
        this.fileType = DEFAULT_FILETYPE; //设置默认运行的文件类型
        this.sizeThreshold = DEFAULT_SIZE_THRESHOLD; //设置默认的缓存大小
        this.sizeMax = DEFAULT_SIZE_MAX; //设置默认的最大文件允许大小
        this.fileLoadPath = loadPath; //设值文件上传目标路径
        this.factory = new DiskFileItemFactory(); //实例化磁盘文件工厂对象
    }

第三个:

/**
     * 保留构造方法
     */
    public FileLoadUtil(){
    

    }

接下来就是一些get 和 set的方法的定义了,这里不会列出,后面会一起把完整的代码列出来。

文件上传的执行流程

我将此执行流程分为一个个的方法,每个方法都作为一个模块,这样可以方便以后扩展和维护。

  1. 先创建临时文件夹
/**
* 创建临时文件夹
* @return 成功返回true失败返回false
*/
public boolean createTempDirectory() {
    
    File tempPatchFile = new File("D:\\temp\\buffer\\");
    //检查目录是否存在
    if (!tempPatchFile.exists()) {
    
        //创建该目录
        if (!tempPatchFile.mkdirs()) {
    
            return false;
        }
    }
    return true;
}
  1. 设置文件上传参数
/**
* 设置文件上传参数
*/
public void setUploadParam() {
    
    //设置缓存大小
    factory.setSizeThreshold(sizeThreshold);
    //设置临时文件夹
    factory.setRepository(new File(tempFilePath));
    //实例化文件上传对象
    upload = new ServletFileUpload(factory);
    //设置上传文件最大大小
    upload.setSizeMax(sizeMax);
}
  1. 处理请求的文件集合
/**
* 多文件上传的的核心
* @param fileItems
* @return 返回上传的文件名称集合
* @throws Exception
*/
public List<String> processFormFile(List<FileItem> fileItems) throws Exception {
    
	//存放文件名的集合
    List<String> nameArr = new ArrayList<>();
    //用于迭代遍历fileItems
    Iterator<FileItem> itemIterator = fileItems.iterator();
    //遍历fileItems集合
    while (itemIterator.hasNext()) {
    
        //获取List<FileItem>集合中的每一个FileItem项
        FileItem fileItem = itemIterator.next();
        //判断该表单是否为file类型(file:false,nofile:true)
        if (!fileItem.isFormField()) {
    
            String name;
            //此处上传单个文件
            if((name = fileUploading(fileItem)) != null)
            	//将文件名保存至集合
                nameArr.add(name);
        }
    }
    return nameArr;
}
  1. 文件上传主要实现
/**
     * 文件上传方法,包括文件类型判断
     * @param fileItem
     * @return null/string
     * @throws Exception
     */
    private String fileUploading(FileItem fileItem) throws Exception {
    
        String fileName = fileItem.getName();
        //将文件类型数组转换为ArrayList集合
        List<String> fileType = Arrays.asList(this.fileType);
        //获取文件后缀名
        String ext = fileName.substring(fileName.lastIndexOf(".") + 1);
        //如果不匹配返回true
        if (!fileType.contains(ext)) {
    
            System.out.println("文件类型不符合");
        } else {
    
            //文件名不能为空和空字符
            if (fileName != null && !fileName.equals("")) {
    
                //目标文件对象
                File fullFile = new File(fileName);
                //上传路径对象
                File fileSave = new File(fileLoadPath, fullFile.getName());
                //将文件上传
                fileItem.write(fileSave);
                //返回文件名
                return fileName;
            }
        }
        return null;
    }

以上4个方法就可以实现多文件上传了,接下来只剩下一个主调方法来将以上的流程组合起来:

/**
* 默认的文件上传主调方法
* @param req
* @return 上传成功的文件集合
* @throws Exception
*/
public List<String> defUpload(HttpServletRequest req) throws Exception{
    
	//先创临时文件夹
    if(!this.createTempDirectory()){
    
        System.out.println("创建文件夹失败");
    }
    //设置文件上传参数
    this.setUploadParam();
    List<FileItem> fileItems = null;
    //判断是否为文件上传表单
    if(ServletFileUpload.isMultipartContent(req)) {
    
    	//从请求中获取文件集合
        fileItems = upload.parseRequest(req);
        //返回文件上传后的文件名称集合
        return this.processFormFile(fileItems);
    }
    return null;
}

至此这个类已经写好了。

前端页面文件提交

我们通常有两种方式提交文件,一个是通过form表单提交,一个是通过ajax异步提交,那么在这个案例中,我将通过使用ajax来提交文件。

<input type = "file"/>
<input type = "file"/>
<input type = "file"/>
<button id = "cli">上传</button>

上面我定义了几个input标签,类型文文件类型,其中没有用到form表单。当我点击上传按钮的时候就会将这三个标签中的文件上传至服务器。
以下是我的js代码,利用了jquery的ajax:

$("#cli").click(function(){
    
	var form = new FormData();
	var fileobjs = new Array();
	for(var i = 0; i < $("input[type='file']").length; i++) {
    
		var ele = document.getElementsByTagName("input");
		fileobjs[i] = ele[i].files[0]
	}
	
	for(var i = 0; i < fileobjs.length; i++) {
    
		form.append("img", fileobjs[i]);
	}
	fileUpload(form)
})

上面是获取input中的文件并封装到FormData的一个过程,然后再将form中的数据交给fileUpload提交到服务器上传。
现在看看fileUpload方法:

function fileUpload(form) {
    
    $.ajax({
    
        type:"post",
        async:false,
        url:"/MyFileUpload/file",
        data:form,
        dataType:"text",
        processData : false, // 使数据不做处理
        contentType : false, // 不要设置Content-Type请求头
        success:function (data) {
    
        },
        error:function(){
    
            alert("FBI Waring")
        }
    })
}

我们在这里要加上这两个属性设置 processData : false, contentType : false,这样请求到服务器是就不会是个对象了,保证了数据的可上传性。

服务端的处理

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
	//文件上传的工具类
	FileLoadUtil fileLoadUtil = new FileLoadUtil("D:/img");
	try {
    
		//获取到成功上传的文件集合
		List<String> list = fileLoadUtil.defUpload(req);

		if (list != null) {
    
			for (String string : list) {
    
				System.out.println(string + "已成功上传...");
			}
			System.out.println(list.size()+"个文件已成功上传");
		} else {
    
			System.out.println("上传失败");
		}
	} catch (Exception e) {
    
		e.printStackTrace();
	}
}

最后我把封装好的工具类奉上,如果是初学可以参考一下,尝试自己改变其中的定义,让他变得更好:

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * @description:
 * @author: LiWenJie
 * @time: 2020/9/11 11:35
 */
public class FileLoadUtil {
    

    private static final String DEFAULT_TEMP_FILEPATH = "D:\\temp\\buffer\\";//默认临时路径

    private static final String[] DEFAULT_FILETYPE = {
    "jpg", "png", "bmp", "gif"};//默认上传的文件类型

    private static final int DEFAULT_SIZE_THRESHOLD = 1024 * 4;//默认缓存大小4k

    private static final int DEFAULT_SIZE_MAX = 1024 * 5000;//默认最大文件大小5mb

    private String fileLoadPath; //上传目标的路径

    private String fileName; //文件名

    private String tempFilePath; //临时文件夹

    private String[] fileType; //允许的文件类型

    private int sizeThreshold; //上传缓存区大小

    private int sizeMax; //上传文件最大大小限制

    private DiskFileItemFactory factory; //磁盘文件工厂

    private ServletFileUpload upload; //文件上传对象

    /**
     * 自定义构造方法
     *
     * @param loadPath
     * @param tempFilePath
     * @param fileType
     * @param sizeThreshold
     * @param sizeMax
     */
    public FileLoadUtil(String loadPath, String tempFilePath, String[] fileType, int sizeThreshold, int sizeMax) {
    
        this.fileLoadPath = loadPath;
        this.tempFilePath = tempFilePath;
        this.fileType = fileType;
        this.sizeThreshold = sizeThreshold;
        this.sizeMax = sizeMax;
    }

    /**
     * 默认构造方法
     * @param loadPath
     */
    public FileLoadUtil(String loadPath) {
    
        this.tempFilePath = DEFAULT_TEMP_FILEPATH;
        this.fileType = DEFAULT_FILETYPE;
        this.sizeThreshold = DEFAULT_SIZE_THRESHOLD;
        this.sizeMax = DEFAULT_SIZE_MAX;
        this.fileLoadPath = loadPath;
        this.factory = new DiskFileItemFactory();
    }

    /**
     * 保留构造方法
     */
    public FileLoadUtil(){
    

    }

    /**
     * 返回默认的临时文件夹
     * @return
     */
    public static String getDefaultTempFilepath() {
    
        return DEFAULT_TEMP_FILEPATH;
    }

    /**
     * 获取上传文件的路径
     * @return
     */
    public String getFileLoadPath() {
    
        return fileLoadPath;
    }

    public void setFileLoadPath(String fileLoadPath) {
    
        this.fileLoadPath = fileLoadPath;
    }

    public String getFileName() {
    
        return fileName;
    }

    public void setFileName(String fileName) {
    
        this.fileName = fileName;
    }

    public String getTempFilePath() {
    
        return tempFilePath;
    }

    public void setTempFilePath(String tempFilePath) {
    
        this.tempFilePath = tempFilePath;
    }

    public String[] getFileType() {
    
        return fileType;
    }

    public void setFileType(String[] fileType) {
    
        this.fileType = fileType;
    }

    public int getSizeThreshold() {
    
        return sizeThreshold;
    }

    public void setSizeThreshold(int sizeThreshold) {
    
        this.sizeThreshold = sizeThreshold;
    }

    public int getSizeMax() {
    
        return sizeMax;
    }

    public void setSizeMax(int sizeMax) {
    
        this.sizeMax = sizeMax;
    }

    /**
     * 创建临时文件夹
     * @return
     */
    public boolean createTempDirectory() {
    
        File tempPatchFile = new File("D:\\temp\\buffer\\");
        //检查目录是否存在
        if (!tempPatchFile.exists()) {
    
            //创建该目录
            if (!tempPatchFile.mkdirs()) {
    
                return false;
            }
        }
        return true;
    }

    /**
     * 设置文件上传参数
     */
    public void setUploadParam() {
    
        //设置缓存大小
        factory.setSizeThreshold(sizeThreshold);
        //设置临时文件夹
        factory.setRepository(new File(tempFilePath));
        //实例化文件上传对象
        upload = new ServletFileUpload(factory);
        //设置上传文件最大大小
        upload.setSizeMax(sizeMax);
    }

    /**
     * 处理请求的文件集合
     * @param fileItems
     * @return
     * @throws Exception
     */
    public List<String> processFormFile(List<FileItem> fileItems) throws Exception {
    
    	//存放文件名的集合
        List<String> nameArr = new ArrayList<>();
        //用于迭代遍历fileItems
        Iterator<FileItem> itemIterator = fileItems.iterator();
        //遍历fileItems集合
        while (itemIterator.hasNext()) {
    
            //获取List<FileItem>集合中的每一个FileItem项
            FileItem fileItem = itemIterator.next();
            //判断该表单是否为file类型(file:false,nofile:true)
            if (!fileItem.isFormField()) {
    
                String name;
                //此处上传单个文件
                if((name = fileUploading(fileItem)) != null)
                	//将文件名保存至集合
                    nameArr.add(name);
            }
        }
        return nameArr;
    }

    /**
     * 文件上传方法,包括文件类型判断
     * @param fileItem
     * @return
     * @throws Exception
     */
    private String fileUploading(FileItem fileItem) throws Exception {
    
        String fileName = fileItem.getName();
        //将文件类型数组转换为ArrayList集合
        List<String> fileType = Arrays.asList(this.fileType);
        //获取文件后缀名
        String ext = fileName.substring(fileName.lastIndexOf(".") + 1);
        //如果不匹配返回true
        if (!fileType.contains(ext)) {
    
            System.out.println("文件类型不符合");
        } else {
    
            //文件名不能为空和空字符
            if (fileName != null && !fileName.equals("")) {
    
                //目标文件对象
                File fullFile = new File(fileName);
                //上传路径对象
                File fileSave = new File(fileLoadPath, fullFile.getName());
                //将文件上传
                fileItem.write(fileSave);
                //返回文件名
                return fileName;
            }
        }
        return null;
    }


    /**
     * 默认的文件上传主调方法
     * @param req
     * @return 上传成功的文件集合
     * @throws Exception
     */
    public List<String> defUpload(HttpServletRequest req) throws Exception{
    
    	//先创临时文件夹
        if(!this.createTempDirectory()){
    
            System.out.println("创建文件夹失败");
        }
        //设置文件上传参数
        this.setUploadParam();
        List<FileItem> fileItems = null;
        //判断是否为文件上传表单
        if(ServletFileUpload.isMultipartContent(req)) {
    
        	//从请求中获取文件集合
            fileItems = upload.parseRequest(req);
            //返回文件上传后的文件名称集合
            return this.processFormFile(fileItems);
        }
        return null;
    }
}

其端页面很灵活,可以自己动手制作

猜你喜欢

转载自blog.csdn.net/qq_43538697/article/details/108626692