13-文件上传

流程

文件上传除了Servlet和jsp依赖的jar包外,还需要额外导入commons-fileupload和commons-io包

过程:
表单提交——>判断表单是否带文件——>是的话,创建保存文件的目录——>创建DiskFileItemFactory工厂,设置阈值,超过阈值转存到临时文件目录——>创建ServletFileUpload,可以设置监听器、编码、可上传文件大小——>servletFileUpload解析请求,获得封装好的FileItem对象——>对于文件对象,创建唯一的UUID目录,将文件转为输入流,通过FileOutputStream写到指定地址

1、表单设置enctype="multipart/form-data"可以用来支持文件上传
2、ServletFileUpload对象可以用来处理请求,将表单数据封装成一个个FileItem对象。创建ServletFileUpload时需要DiskFileItemFactory 对象,也可以通过set的方式设置。
13-文件上传

3、为了保证安全,上传的文件应该放在外界无法直接访问的目录下,比如WEB-INF下
4、为防止上传文件覆盖,应该创建唯一的文件夹 UUID.randomUUID().toString()
5、可以给DiskFileItemFactory对象设置个阈值,超过阈值就将文件放入另一个文件夹(缓存,可以过段时间删除)
13-文件上传

6、设置上传文件的最大值
13-文件上传
7、可以对文件后缀进行检测,判断是否接收

代码

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
<%--  通过表单上传文件   get上传文件有限制    post没有--%>
  <form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
    上传用户:<input type="text" name="username"><br/>
    <p><input type="file" name="file1"></p>
    <p><input type="file" name="file2"></p>
    <p><input type="submit"> | <input type="reset"></p>
  </form>
  </body>
</html>

FileServlet

public class FileServlet extends javax.servlet.http.HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //判断上传文件的方式是不是post,文件是普通表单还是带文件的表单
        if (!ServletFileUpload.isMultipartContent(req)) {
            return;   //如果不符合,就return中止
        }

        //创建文件上传的保存路径,建议在WEB-INF下面,这样用户无法直接访问
        String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
        File uploadfile = new File(uploadPath);
        if (!uploadfile.exists()) {  //文件不存在,就建立一个
            uploadfile.mkdir();
        }

        //缓存。如果文件大小超过预期,就将文件放在一个临时文件中,过几天删除,或者提醒用户转为永久
        String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
        File tempfile = new File(tempPath);
        if (!tempfile.exists()) {
            tempfile.mkdir();
        }

        //处理上传文件,一般都需要通过流来获取。我们可以使用原生态的request.getInputStream获取流,
        // 但是太麻烦了。因此使用Apache文件上传组件来实现。使用common-fileupload,它依赖于commons-io组件
        try {
            //1、创建DiskFileItemFactory工厂,设置阈值,超过阈值转存临时文件
            DiskFileItemFactory factory = getDiskFileItemFactory(tempfile);

            //2、获取ServletFileUpload,可以设置监听器、编码、可上传文件大小
            ServletFileUpload servletFileUpload = getServletFileUpload(factory);

            //3、上传文件
            String msg = uploadParseRequest(servletFileUpload, req, uploadPath);

            //上传完消息传回前端
            req.setAttribute("msg", msg);
            req.getRequestDispatcher("/info.jsp").forward(req, resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    public static DiskFileItemFactory getDiskFileItemFactory(File file) {
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //缓冲区阈值,超过这个阈值,就将文件放入临时文件中
        factory.setSizeThreshold(1024*1024);
        //设置临时目录
        factory.setRepository(file);
        return factory;
    }

    public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
        //获取ServletFileUpload
        ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
        //设置监听器
        servletFileUpload.setProgressListener(new ProgressListener() {
            @Override
            public void update(long l, long l1, int i) {
                System.out.println("总大小:" + l1 + " 已上传:" + l);
            }
        });
        //处理乱码问题
        servletFileUpload.setHeaderEncoding("utf-8");
        //设置单个文件的最大大小
        servletFileUpload.setFileSizeMax(1024 * 1024 * 10);
        //设置总文件的最大大小
        servletFileUpload.setSizeMax(1024 * 1024 * 10);
        return servletFileUpload;
    }

    public static String uploadParseRequest(ServletFileUpload servletFileUpload, HttpServletRequest request, String uploadPath)
            throws Exception {

        String msg = "";
        //解析请求,并封装为FileItem对象
        List<FileItem> fileItems = servletFileUpload.parseRequest(request);
        for (FileItem fileItem : fileItems) {
            if (fileItem.isFormField()) {
                //普通的表单字段
                //getFieldName是获得控件的名字,getName是获得传入的文件的名字。因此对于普通的表单字段,getName()为null
                String fieldname = fileItem.getFieldName();  //前端控件的名字
                String value = fileItem.getString("utf-8");   //获取String值
                System.out.println(fieldname + "  " + value);
            } else {
                //====================处理文件名======================
                String name = fileItem.getName();
                System.out.println(name);
                //名字不符合就下一个
                if (name.trim().equals("") || name == null) {
                    continue;
                }
                //获取最后的文件名
                String filename = name.substring(name.lastIndexOf('/') + 1);
                //获取后缀
                String type = name.substring(name.lastIndexOf('.' )+1);
                System.out.println("文件信息[文件名:" + filename + "  类型:" + type);
                //UUID保证文件名唯一
                String uuid = UUID.randomUUID().toString();
                //====================设置存放地址======================
                //文件真实存放目录
                String path = uploadPath + "/" + uuid;
                File file = new File(path);
                if (!file.exists()) {
                    file.mkdir();
                }
                //====================传输======================
                //获取文件输入流
                InputStream inputStream = fileItem.getInputStream();
                //获取文件输出流
                FileOutputStream outputStream = new FileOutputStream(path + "/" + filename);
                //设置缓冲区
                byte[] buffer = new byte[2048];
                //读写
                int len = 0;
                while ((len = inputStream.read(buffer)) > 0) {
                    outputStream.write(buffer, 0, len); //取buffer中的0到len
                }
                inputStream.close();
                outputStream.close();
            }
            msg = "上传成功";
        }
        return msg;
    }
}

info.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ${msg}
</body>
</html>

web.xml

    <servlet>
        <servlet-name>FileServlet</servlet-name>
        <servlet-class>com.yuan.servlet.FileServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FileServlet</servlet-name>
        <url-pattern>/upload.do</url-pattern>
    </servlet-mapping>
上一篇:文件的上传操作


下一篇:Java Web文件上传(感谢秦疆老师)