专栏首页技术进阶之路Servlet 3.0 文件上传与下载

Servlet 3.0 文件上传与下载

一、文件上传代码实现

代码实现很简单:

主要是用到了客户端 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要有图片,才可以完成下载。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JSP 页面中的 路径问题

    上面两种写法是相同的,都是指向 webapp 应用程序下的 login.jsp 页面。

    wsuo
  • JavaScript学习笔记(三)

    运行期环境是由宿主环境通过脚本引擎创建的,实际上是由JavaScript引擎创建的一个代码解析初始化环境。

    wsuo
  • 前后端分离中使用 Session 域传输对象

    前端使用 Vue,后端使用 SpringBoot 框架,使用 Session 传值后端获取不到。

    wsuo
  • 聊聊springboot session timeout参数设置

    本文主要介绍下spring boot中对session timeout参数值的设置过程。

    codecraft
  • JavaWeb项目之电话本,两个版本,以及总结反思

    使用技术: Oracle 数据库 前端后台: Servlet + jsp + JDBC + html + css + js 前端界面自定, 但一定实现需要的功能...

    二十三年蝉
  • Apache Struts2 Remote Code Execution (S2-045)

    风流
  • 3. 源码分析---SOFARPC客户端服务调用

    所以当我们用BoltClientProxyInvoker#invoke的时候实际上是调用了父类的invoke方法 ClientProxyInvoker#inv...

    luozhiyun
  • Android Volley完全解析(四),带你从源码的角度理解Volley

    经过前三篇文章的学习,Volley的用法我们已经掌握的差不多了,但是对于Volley的工作原理,恐怕有很多朋友还不是很清楚。因此,本篇文章中我们就来一起阅读一下...

    用户1158055
  • SpringMVC工作原理流程(二)

    当有请求过来,首先会先调用HttpServlet的service(ServletRequest req, ServletResponse res)方法,在ser...

    秋白
  • koa源码阅读[0]

    Node.js也是写了两三年的时间了,刚开始学习Node的时候,hello world就是创建一个HttpServer,后来在工作中也是经历过Express、K...

    贾顺名

扫码关注云+社区

领取腾讯云代金券