模拟文件上传(三):使用apache fileupload组件进行文件批量上传
阅读原文时间:2023年07月12日阅读:2

其中涉及到的jar包

jsp显示层:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>文件上传</title>
  </head>
  <body>
       <form action="${pageContext.servletContext.contextPath }/servlet/UpLoadDemo03" method="POST" enctype="multipart/form-data">
            请选择要上传的文件一:<input type="file" name="attachment01" /><br/>
            请选择要上传的文件二:<input type="file" name="attachment02" /><br/>
            请选择要上传的文件三:<input type="file" name="attachment03" /><br/>
            <input type="submit" value="上传文件"/>
       </form>
  </body>
</html>

成功后跳转的显示文件信息的界面:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>success</title>
  </head>
  <body>
       <h3>文件上传成功! </h3>
    <table border="1" width="500px">
        <tr>
            <th>编号</th>
            <th>文件名</th>
            <th>大小</th>
            <th>类型</th>
            <th>上传时间</th>
        </tr>
        <c:forEach items="${fileList}" var="bean" varStatus="varSta">
        <tr>
            <td>${varSta.count }</td>
            <td>${bean.name }</td>
            <td>${bean.size }</td>
            <td>${bean.type }</td>
            <td>${bean.addTime }</td>
        </tr>
        </c:forEach>
    </table>
  </body>
</html>

其中封装的文件信息的JavaBean:

package entity;

public class FileBean {
    private String name; // 文件名称
    private String size; // 大小
    private String type; // 类型
    private String addTime; // 上传时间
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSize() {
        return size;
    }
    public void setSize(String size) {
        this.size = size;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getAddTime() {
        return addTime;
    }
    public void setAddTime(String addTime) {
        this.addTime = addTime;
    }

}

servlet逻辑层代码:

package upload;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;

import entity.FileBean;
/**
 * 多文件上传!
 *
 * 使用apache的文件上传和下载的组件
 * 1.导入jar包
 *         commons-fileload-1.2.2.jar
 *         commons-io-2.1.jar 一个IO流工具(更方便)
 * @author mzy
 *
 */
public class UpLoadDemo03 extends HttpServlet {

    private static final long serialVersionUID = 987003232758385500L;

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        DecimalFormat df = new DecimalFormat("#.00");
        try {
            DiskFileItemFactory factory = new DiskFileItemFactory(10*1024, new File("e:/temp"));

            ServletFileUpload upload = new ServletFileUpload(factory);

            /* 3.解析文件
             * 该方法会自动读取请求的实体内容中所有上传文件的信息。
             * List:可以是多个文件
             *
             * 其中解析request中的文件的个数:
             *      需要注意的是,并不一定是用户实际上传的文件数量
             * 如果我jsp中有三个input标签,但是用户只上传了两个,就
             * submit了;但是在实际解析request的时候,还是解析的三
             * 个文件,因为解析的文件个数是由input标签的个数决定的!
             * 所以在这种情况下,三个input只使用了两个的话,就会报错!
             * 可能要通过异常处理,自定义此异常在实际运用中解决!
             *
             * 其次:
             *      注意jsp中进行文件传递的input标签(type="file")
             *      必须要有name属性,因为在源码构造的时候,需要传入
             *      name属性进行文件解析(虽然我们使用不到name属性)
             *
             * 然后:
             *      文件名相同情况,不能解决,如果上传的文件相同直接
             * 覆盖掉了!
             * 可能首先要对目录下的file文件进行名字判断isEixt?
             */

            List<FileItem> list = upload.parseRequest(request);
            /*
             * 我们将每个文件的基本信息存放到我们构建的文件的javaBean对象中去!
             * 最后上传成功之后,显示到表现层!
             */
            List<FileBean> fileList = new ArrayList<FileBean>();
            /*
             * 设置文件头编码,来解决某些服务端默认编码造成的中文乱码问题!
             */
            upload.setHeaderEncoding("utf-8");

            // 将上传的文件的信息读取出来
            for (FileItem item : list) {
                String name = item.getName();
                if(name.contains("\\")) {
                    name = name.substring(name.lastIndexOf("\\")+1, name.length());
                }
                // 文件大小:单位应该是KB
                long size = item.getSize();
                // 类型
                String contentType = item.getContentType();
                /*
                 * 对文件的大小单位做转化:
                 * 1024B = 1KB
                 * 1024*1024B = 1MB
                 * 1024*1024*1024B = 1GB
                 */
                String sizeString;
                double tempSize;
                if(size >= 1024 && size < 1024 * 1024) {
                    tempSize = size/1024.0;
                    sizeString = df.format(tempSize)+"KB";
                } else if(size > 1024 * 1024 &&
                        size <= 1024 * 1024 * 1024) {
                    tempSize = size/(1024*1024.0);
                    sizeString = df.format(tempSize)+"MB";
                } else if(size >= 1024 * 1024 * 1024) {
                    tempSize = size/(1024*1024*1024.0);
                    sizeString = df.format(tempSize)+"GB";
                } else {
                    sizeString = size+"B";
                }
                // 封装FileBean对象
                FileBean bean = new FileBean();
                bean.setName(name);
                bean.setType(contentType);
                bean.setSize(sizeString);
                bean.setAddTime(sdf.format(new Date()));
                // 将bean对象放入到fileList中去!
                fileList.add(bean);

                // 文件内容
                InputStream in = item.getInputStream();

                FileUtils.copyInputStreamToFile(in, new File("e:/files/"+name));

                /*
                 * 注意:
                 *      在我文件上传完成之后,本地的临时文件
                 *      不会自动删除,所以要我们手动的进行删除!
                 */
                item.delete();
            }
            request.setAttribute("fileList", fileList);
            /*
             * 请求转发是浏览器行为:
             *      success.jsp界面直接位于webRoot根目录下
             */
            request.getRequestDispatcher("/03.upload_success.jsp").forward(request, response);
        } catch (Exception e) {
            e.printStackTrace();
            // throw new RuntimeException(e.getMessage());
        }

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        doGet(request, response);
    }

}

其中提到的多个input,有传空值的情况下,前端约束案例