← 返回首页
Servlet基础教程(二十一)
发表时间:2020-04-10 00:51:00
讲解Servlet实现文件上传

在Servlet2.5中,我们要实现文件上传功能时,一般都需要借助第三方开源组件,例如Apache的commons-fileupload组件,在Servlet3.0中提供了对文件上传的原生支持,我们不需要借助任何第三方上传组件,直接使用Servlet3.0提供的API就能够实现文件上传功能了。

实现步骤

1)编写文件上传静态页面upload.html

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<h1>Servlet实现文件上传</h1>
<hr>
<form action="upload" enctype="multipart/form-data" method="post">
    上传人:<input type="text" name="username">
    选择文件:
    <input type="file" name="upload">
    <input type="submit" value="上传">
</form>
</body>
</html>

2)创建com.utils包,创建FileUtils工具类。

package com.utils;

import java.io.File;
import java.util.Map;
import java.util.UUID;

public class FileUtils {
    /**
     * 根据hash打散文件,然后获取保存目录
     *
     * @param filename     文件名称
     * @param fileSaveRoot 文件保存根目录
     * @return 文件实际保存目录
     */
    public static String fileSave(String filename, String fileSaveRoot) {
        int hash = filename.hashCode();
        int dir1 = hash & 0xf;//0-15
        int dir2 = (hash & 0xf0) >> 4;//0-15

        String fileSavePath = fileSaveRoot + File.separator + dir1 + File.separator + dir2;
        System.out.println(fileSavePath);
        File file = new File(fileSavePath);
        if (!file.exists()) {
            //二级目录需要连续创建两个
            file.mkdirs();
        }
        return fileSavePath;
    }


    // 防止文件提交上来重复名字,所以加上唯一的UUID
    public static String makeFileName(String fileName) {
        return UUID.randomUUID().toString() + "_" + fileName;
    }


    /**
     *
     * 主要是为了之后展示给用户看,带上UUID不是很难受?
     *
     * @param fileUUIDName UUID文件名
     * @return 截取之后的名字
     */
    public static String extractFileName(String fileUUIDName) {
        int index = fileUUIDName.indexOf("_");
        return fileUUIDName.substring(index + 1);
    }


    /**
     * 递归遍历文件树,将值存进map中便于jsp展示
     *
     * @param f 文件
     * @param map 存放文件的map,键是UUID名字,值是截取UUID后的
     */
    public static void putFiles(File f, Map<String, String> map) {
        File[] files = f.listFiles();
        for (File file : files) {
            if (file == null) {
                //回溯点
                return;
            }
            if (file.isDirectory()) {
                putFiles(file, map);
            } else {
                String fileUUIDName = file.getName();
                String fileName = extractFileName(fileUUIDName);
                map.put(fileUUIDName, fileName);
            }
        }
    }
}

3)在com.servlet包下创建FileUploadServlet

package com.servlet;

import com.utils.FileUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.UUID;

@WebServlet(name = "FileUploadServlet", value = "/upload")
@MultipartConfig(maxFileSize = 1000 * 1024 * 1024,
        maxRequestSize = 1000 * 1024 * 1024)
public class FileUploadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //request.setCharacterEncoding("UTF-8");

        String username = request.getParameter("username");
        System.out.println("上传用户:" + username);

        String savePathRoot = this.getServletContext().getRealPath("/WEB-INF/upload");
        System.out.println(savePathRoot);

        Collection<Part> parts = request.getParts();
        for (Part part : parts) {

            /*Collection<String> headerNames = part.getHeaderNames();
            for (String name : headerNames) {
                System.out.println(name);
            }*/

            //获得提交的名字
            String filename = part.getSubmittedFileName();
            System.out.println(filename);

            //对于不是上传文件的input会传来空值,或者你没有指定上传的文件也是null,这里过滤一下
            if (filename == null) {
                continue;
            }
            String fileUUIDName = FileUtils.makeFileName(filename);
            String saveDir = FileUtils.fileSave(fileUUIDName, savePathRoot);
            /*long size = part.getSize();*/

            //File.separator是自适应的windows和linux分隔符就是\\和/
            part.write(saveDir + File.separator + fileUUIDName);
            //删除临时文件
            part.delete();
        }
    }
}

4)测试上传文件。 启动tomcat服务器,运行upload.html,测试文件上传。

控制台输出效果:

上传用户:张三丰
D:\servlet_course\out\artifacts\helloservlet_war_exploded\WEB-INF\upload
null
Tomcat简介001.png
D:\servlet_course\out\artifacts\helloservlet_war_exploded\WEB-INF\upload\1\5

可以在D:\servlet_course\out\artifacts\helloservlet_war_exploded\WEB-INF\upload\1\5目录下发现上传成功的文件a385e7c8-4fad-43e3-b449-bede79b61102_Tomcat简介001.png