一、文件上传代码实现

代码实现很简单:

主要是用到了客户端 HTML 页面的表单元素,使用<form> 标签的 enctype 属性,并设置它的值为 multipart/formdata,意思是:多部分/表单数据,同时使用<input type="file"> 的输入域用于指定上传的文件。

关于form表单 enctype属性:

描述
application/x-www-form-urlencoded 在发送前编码所有字符(默认)
multipart/form-data 不对字符编码,每一个表单项分割为一个部件
text/plain 空格转换为加号,但不对特殊字符编码

这是前端代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>文件上传</title>
  </head>
  <body>
  ${message}<br>
  <form action="fileUpload" method="post" enctype="multipart/form-data">
    <table>
      <tr>
        <td align="center" colspan="2">文件上传</td>
      </tr>
      <tr>
        <td>用户名: </td>
        <td><input type="text" name="username" size="30"></td>
      </tr>
      <tr>
        <td>文件: </td>
        <td><input type="file" name="filename" size="30"></td>
      </tr>
      <tr>
        <td><input type="submit" value="提交"></td>
        <td><input type="reset" value="重置"></td>
      </tr>
    </table>
  </form>
  </body>
</html>

这是后台的接口:

@WebServlet(name = "FileUploadServlet", urlPatterns = "/fileUpload")
@MultipartConfig(location = "D:\\", fileSizeThreshold = 1024)
public class FileUploadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String path = this.getServletContext().getRealPath("/");//返回web应用程序文档根目录
        String username = request.getParameter("username");
        Part part = request.getPart("filename");
        String message = "";

        if (part.getSize() > 1024 * 1024) {
            part.delete();
            message = "文件大小不能超过1MB";
        } else {
            path += "\\user\\" + username;
            File file = new File(path);
            if (!file.exists()) {
                file.mkdirs();
            }
            String h = part.getHeader("Content-Disposition");
            String fname = getFileName(h);
            part.write(path + "\\" + fname);
            message = "文件上传成功";
        }
        request.setAttribute("message", message);
        request.getRequestDispatcher("/index.jsp").forward(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    /** * 根据请求头解析出文件名 * 请求头的格式:火狐和google浏览器下:form-data; name="file"; filename="snmp4j--api.zip" * IE浏览器下:form-data; name="file"; filename="D:\snmp4j--api.zip" * @param header 请求头 * @return 文件名 */
    public String getFileName(String header) {
        /** * String[] tempArr1 = header.split(";"); * 代码执行完之后,在不同的浏览器下,tempArr1数组里面的内容稍有区别: * 火狐或者google浏览器下:tempArr1={form-data,name="file",filename="snmp4j--api.zip"} * IE浏览器下:tempArr1={form-data,name="file",filename="D:\snmp4j--api.zip"} */
        String[] tempArr1 = header.split(";");
        /** *火狐或者google浏览器下:tempArr2={filename,"snmp4j--api.zip"} *IE浏览器下:tempArr2={filename,"D:\snmp4j--api.zip"} */
        String[] tempArr2 = tempArr1[2].split("=");
        //获取文件名,兼容各种浏览器的写法
        String fileName = tempArr2[1].substring(tempArr2[1].lastIndexOf("\\")+1).replaceAll("\"", "");
        return fileName;
    }
}

假如上传了一张图图片:

那么请求头信息为:


二、原理分析

当表单提交的时候,浏览器将表单的各部分发送到服务器端,在服务器端使用 partwrite()方法可以将文件保存在服务器的特定位置。

Part 接口为 Servlet3.0 新增的接口,在servlet.http 包下,它表示多部分表单的一个部分。

  • public String getHeader(String name):返回Part对象指定的MIME头的值。
  • public long getSize():返回Part 对象的大小。
  • public void write(String path):将Part对象写入到指定的位置。

必须使用@MultipartConfig注解:

  • 该注解告诉容器该 Servlet 能够处理 multipart/formdata的请求。
  • 使用该注解request对象才可以得到表单的各部分

常用的注解元素为:

也可以使用配置文件的方式进行配置,元素值与标签相同。

三、文件下载

/** * 文件下载 servlet */
@WebServlet(urlPatterns = "/downloadServlet")
public class DownloadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1、文件存放路径
        String path = "D:/fileUpload/";
        // 2、需要下载的文件名
        String fileName = "test.jpg";
        File file = new File(path + fileName);
        response.reset();
        response.setCharacterEncoding("UTF-8");
        fileName = URLEncoder.encode(fileName, "UTF-8");
        response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
        InputStream input = new FileInputStream(file);
        ServletOutputStream out = response.getOutputStream();
        byte[] buff = new byte[1024];
        int len;
        while ((len = input.read(buff)) != -1) {
            out.write(buff, 0, len);
            out.flush();
        }
        input.close();
        out.close();
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

D:\fileUpload\test.jpg要有图片,才可以完成下载。