EmmmuaCode EmmmuaCode
首页​
导航🚀​
  • 数据结构
  • 计算机网络
  • Java基础

    • JavaSE
    • JVM虚拟机
    • JUC并发编程
  • JavaWeb

    • Servlet
    • MVC
    • filter|listener
  • HTML
  • CSS
  • JavaScript
  • Vue
  • uni-app
  • Spring5
  • SpringMVC
  • SpringBoot2
  • SpringCloud
  • SpringSecurity
  • 搜索引擎

    • ElasticSearch
  • 消息队列

    • RabbitMQ
  • 服务器

    • Nginx🌐
  • 服务框架

    • Dubbo
  • Python基础
  • 数据分析
  • Hadoop
  • SQL 数据库

    • MySQL
  • NoSQL 数据库

    • NoSQL数据库概论
    • Redis
    • MongoDB
    • HBase
  • 框架

    • MyBatis
    • MyBatis-Plus
    • ShardingSphere
  • 部署

    • Linux
    • Docker
  • 管理

    • Maven
    • Git
  • 友情链接
  • 优秀博客文章
  • 索引

    • 分类
    • 标签
    • 归档
  • 其他

    • 关于
Github (opens new window)

wufan

海内存知己,天涯若比邻。
首页​
导航🚀​
  • 数据结构
  • 计算机网络
  • Java基础

    • JavaSE
    • JVM虚拟机
    • JUC并发编程
  • JavaWeb

    • Servlet
    • MVC
    • filter|listener
  • HTML
  • CSS
  • JavaScript
  • Vue
  • uni-app
  • Spring5
  • SpringMVC
  • SpringBoot2
  • SpringCloud
  • SpringSecurity
  • 搜索引擎

    • ElasticSearch
  • 消息队列

    • RabbitMQ
  • 服务器

    • Nginx🌐
  • 服务框架

    • Dubbo
  • Python基础
  • 数据分析
  • Hadoop
  • SQL 数据库

    • MySQL
  • NoSQL 数据库

    • NoSQL数据库概论
    • Redis
    • MongoDB
    • HBase
  • 框架

    • MyBatis
    • MyBatis-Plus
    • ShardingSphere
  • 部署

    • Linux
    • Docker
  • 管理

    • Maven
    • Git
  • 友情链接
  • 优秀博客文章
  • 索引

    • 分类
    • 标签
    • 归档
  • 其他

    • 关于
Github (opens new window)
  • Java 基础

    • Java 概述
    • Java 变量
    • Java 运算符
    • Java 程序控制结构
    • Java 数组、排序和查找
    • Java 面向对象
    • Java 枚举和注解
    • Java 异常-Exception
    • Java 常用类
    • Java 集合
    • Java 泛型
    • Java 多线程
    • Java IO流
    • Java 网络编程
    • Java 多用户即时通信系统
    • Java 反射
    • Java JDBC和数据库连接池
    • Java 正则表达式
    • Java 8新特性
  • JVM

    • 基础篇
    • 实战篇
    • 高级篇
    • 原理篇
    • 面试篇
  • JUC 并发编程

    • 进程与线程
    • Java 线程
    • 共享模型之管程
    • 共享模型之内存
    • 无锁
    • 享元模式
    • 线程池
    • 同步器
    • 并发包
  • Servlet

    • IDEA的使用
    • HTTP协议与Tomcat服务器
    • Servlet 概论
    • HttpServletRequest对象
    • HttpServletResponse对象
    • Cookie 对象
    • HttpSession对象
    • ServletContext对象
    • 文件的上传和下载
      • 文件上传
        • 前台页面
        • 后台实现
      • 文件下载
        • 超链接下载
        • 后台实现下载
  • MVC 三层架构

    • MVC 三层架构
  • 拦截器|监听器

    • 过滤器|监听器
  • studynotes
  • JavaEE
  • JavaWeb
wufan
2022-01-14
目录

文件的上传和下载

# 文件的上传和下载

在上网的时候我们常常遇到文件上传的情况,例如上传头像、上传资料等;当然除了上传,遇见下载的情况也很多,接下来看看我们 servlet 中怎么实现文件的上传和下载。

# 文件上传

文件上传涉及到前台页面的编写和后台服务器端代码的编写,前台发送文件,后台接收并保存文件,这才是一个完整的文件上传。

# 前台页面

在做文件上传的时候,会有一个上传文件的界面,首先我们需要一个表单,并且表单的请求方式为POST;其次我们的 form 表单的 enctype 必须设为"multipart/form-data",即enctype="multipart/form-data",意思是设置表单的类型为文件上传表单。默认情况下这个表单类型是 "application/x-www-form-urlencoded", 不能用于文件上传。只有使用了multipart/form-data 才能完整地传递文件数据。

<!--
文件上传表单
	1. 表单提交类型 method="post"
	2. 表单类型 enctype="multipart/form-data"
	3. 表单元素类型 文件域设置name属性值
-->
<form method="post" action="uploadServlet" enctype="multipart/form-data">
	姓名:<input type="text" name="uname" > <br>
	文件:<input type="file" name="myfile" > <br>
	<button type="submit">提交</button>
</form>
1
2
3
4
5
6
7
8
9
10
11
Click to view the code writen by the author
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
</head>
<body>
<!--
    文件上传
        1.准备表单
        2.设置表单的提交类型为POST请求 method="post"
        3.设置表单类型为文件上传表单 enctype="multipart/form-data"
        4.设置文件提交的地址
        5.准备表单元素
            1.普通的表单项 type="text"
            2.文件项      type="file"
        6.设置表单元素name属性值(表单提交一定要设置表单元素的name属性值,否则后台无法接受数据!)
        -->
    <form method="post" enctype="multipart/form-data" action="UploadServlet">
        姓名:<input type="text" name="uname">  <br>
        文件:<input type="file" name="myfile"> <br>
        <!--button默认的类型是提交类型 type="submit"-->
        <button>提交</button>
    </form>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 后台实现

使用注解 **@MultipartConfig **将一个 Servlet 标识为支持文件上传。 Servlet 将 multipart/form-data的 POST 请求封装成 Part,通过 Part 对上传的文件进行操作。

@WebServlet("/uploadServlet")
@MultipartConfig // 如果是文件上传表单,一定要加这个注解
public class UploadServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 设置请求的编码格式
		request.setCharacterEncoding("UTF-8");
		// 获取普通表单项 (文本框)
		String uname = request.getParameter("uname"); // "uname"代表的是文本框的name属性值
		// 通过 getPart(name) 方法获取Part对象 (name代表的是页面中file文件域的name属性值)
		Part part = request.getPart("myfile");
    	// 通过Part对象,获取上传的文件名
		String fileName = part.getSubmittedFileName();
		// 获取上传文件需要存放的路径 (得到项目存放的真实路径)
		String realPath = request.getServletContext().getRealPath("/");
		// 将文件上传到指定位置
		part.write(realPath + fileName);
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Click to view the code writen by the author
/**
 * @author frx
 * @version 1.0
 * @date 2022/1/14  16:16
 *
 */
@WebServlet("/UploadServlet")
@MultipartConfig
public class UploadServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("文件上传...");

        //设置请求的编码格式
        req.setCharacterEncoding("UTF-8");

        //获取普通表单页(获取参数)
        String uname = req.getParameter("uname");//表单中表单元素的name属性值
        System.out.println("uname:"+uname);

        //获取Part对象 (Servlet将multipart/form-data的 POST 请求封装成 Part)
        Part part = req.getPart("myfile");//表单中file文件域的name属性值

        //通过Part对象得到上传的文件名
        String fileName = part.getSubmittedFileName();
        System.out.println("上传文件名: "+fileName);

        //得到文件存放的路径
        String filePath = req.getServletContext().getRealPath("/");
        System.out.println("文件存放的路径:"+filePath);

        //上传文件到指定目录
        part.write(filePath+"/"+fileName);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  • 访问URL

01

  • 控制台

01

  • 查看文件是否存在

01

# 文件下载

文件下载,即将服务器上的资源下载(拷贝)到本地,我们可以通过两种方式下载。第一种是通过超链接本身的特性来下载;第二种是通过代码下载。

# 超链接下载

当我们在 HTML 或 JSP 页面中使用a标签时,原意是希望能够进行跳转,但当超链接遇到浏览器不识别的资源时会自动下载;当遇见浏览器能够直接显示的资源,浏览器就会默认显示出来,比如 txt、png、jpg 等。当然我们也可以通过download 属性规定浏览器进行下载。但有些浏览器并不支持。

  • 默认下载
<!-- 当超链接遇到浏览器不识别的资源时,会自动下载 -->
<a href="test.zip">超链接下载</a>
1
2
  • 指定 download 属性下载
<!-- 当超链接遇到浏览器识别的资源时,默认不会下载。通过download属性可进行下载 -->
<a href="test.txt" download>超链接下载</a>
1
2

download 属性可以不写任何信息,会自动使用默认文件名。如果设置了download属性的值,则使用设置的值做为文件名。当用户打开浏览器点击链接的时候就会直接下载文件。

Click to view the code writen by the author
<!--download.html文件-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件下载</title>
</head>
<body>
<!--
    超链接下载
        当使用超链接(a标签)时,如果遇到浏览器能够识别的资源,则会显示内容;
        如果遇到浏览器不能识别的资源,则会进行下载
    download 属性
        download 属性可以不写任何信息,会自动使用默认文件名。
        如果设置了download属性的值,则使用设置的值做为文件名。
        当用户打开浏览器点击链接的时候就会直接下载文件。-->
    <!--浏览器能识别的资源-->
    <a href="download/test.txt">文本文件</a>
    <a href="download/test.png">图片文件</a>
    
    <!--浏览器不能识别的资源-->
    <a href="download/test.rar">压缩文件</a>

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  • 访问URL

01

  • 点击压缩文件

01

  • 设置download属性
Click to view the code writen by the author
<!--向download.html中增加以下内容-->
<h2>
    <a href="download/test.txt" download>文本文件</a>
    <a href="download/test.png" download="桌面.png">图片文件</a>
</h2>
1
2
3
4
5
  • 效果

01

# 后台实现下载

  • 实现步骤
  1. 需要通过 response.setContentType 方法设置 Content-type 头字段的值, 为浏览器无法使用某 种方式或激活某个程序来处理的 MIME 类型,例 如 "application/octet-stream" 或 "application/x-msdownload" 等。
  2. 需要通过 response.setHeader 方法设置 Content-Disposition 头的值为 "attachment;filename=文件名"
  3. 读取下载文件,调用 response.getOutputStream 方法向客户端写入附件内容。
public class DownloadServlet extends HttpServlet {
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 设置请求的编码
		request.setCharacterEncoding("UTF-8");
		// 获取文件下载路径
		String path = getServletContext().getRealPath("/");
		// 获取要下载的文件名
		String name = request.getParameter("fileName");
		// 通过路径得到file对象
		File file = new File(path + name);
		// 判断file对象是否存在,且是否是一个标准文件
		if (file.exists() && file.isFile()) {
			// 设置响应类型 (浏览器无法使用某种方式或激活某个程序来处理的类型)
			response.setContentType("application/x-msdownload");
			// 设置头信息
			response.setHeader("Content-Disposition", "attachment;filename=" +
name);
			// 得到输入流
			InputStream is = new FileInputStream(file);
			// 得到输出流
			ServletOutputStream os = response.getOutputStream();
			// 定义byte数组
			byte[] car = new byte[1024];
			// 定义长度
			int len = 0;
			// 循环 输出
			while ((len = is.read(car)) != -1) {
				os.write(car, 0, len);
			}
			// 关闭流 释放资源
			os.close();
			is.close();
		} else {
			System.out.println("文件不存在,下载失败!");
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Click to view the code writen by the author
<!--向download.html中增加以下内容-->
<hr>
    <form action="downloadServlet">
        文件名:<input type="text" name="fileName" placeholder="请输入要下载的文件名">
        <button>下载</button>
    </form>
</hr>
1
2
3
4
5
6
7
/**
 * @author frx
 * @version 1.0
 * @date 2022/1/14  17:24
 * 1. 需要通过 response.setContentType 方法设置 Content-type 头字段的值, 为浏览器无法使用某
 *    种方式或激活某个程序来处理的 MIME 类型,例 如 "application/octet-stream" 或 "application/x-msdownload" 等。
 * 2. 需要通过 response.setHeader 方法设置 Content-Disposition 头的值为 "attachment;filename=文件名"
 * 3. 读取下载文件,调用 response.getOutputStream 方法向客户端写入附件内容。
 */
@WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("文件下载...");

        //设置请求的编码格式
        req.setCharacterEncoding("UTF-8");

        //获取参数(得到要下载的文件名)
        String fileName = req.getParameter("fileName");
        //参数的非空判断  trim():去除字符串前后空格
        if(fileName==null || "".equals(fileName.trim())){
            resp.setContentType("text/html;charset=UTF-8");
            resp.getWriter().write("请输入要下载的文件名!");
            resp.getWriter().close();
            return;

        }
        //得到图片存放的路径
        String path = req.getServletContext().getRealPath("/download/");

        //通过路径的到file对象
        File file = new File(path + fileName);
        //判断文件是否存在
        if(file.exists() && file.isFile()){

            //设置相应类型(为浏览器无法使用某种方式或激活某个程序来处理的 MIME 类型)
            resp.setContentType("application/x-msdownload");
            //设置响应头
            resp.setHeader("Content-Disposition","attachment;filename= "+fileName);
            //得到输入流
            FileInputStream in = new FileInputStream(file);
            //得到字节输出流
            ServletOutputStream out = resp.getOutputStream();
            //定义一个byte数组
            byte[] bytes = new byte[1024];
            //定义长度
            int len=0;
            //循环输出
            while ((len=in.read(bytes))!=-1){
                //输出
                out.write(bytes,0,len);
            }
            //关闭资源
            out.close();
            in.close();


        }else {
            resp.setContentType("text/html;charset=UTF-8");
            resp.getWriter().write("文件不存在,请重试!");
            resp.getWriter().close();
        }


    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  • 访问URL

01

  • 不输入任何点击下载

01

  • 输入不存在的文件名,点击下载

01

  • 存入存在的文件,点击下载

01

下载成功!

#JavaWeb
上次更新: 2024/04/21, 09:42:22
ServletContext对象
MVC 三层架构

← ServletContext对象 MVC 三层架构→

最近更新
01
微信支付功能的实现与流程
11-21
02
购物车与结算区域的深入优化与功能完善
11-21
03
购物车与结算区域的功能实现与优化
11-21
更多文章>
Theme by Vdoing | Copyright © 2023-2024 EmmmuaCode | 黔ICP备2022009864号-2
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式