需求分析

  • 页面显示超链接
  • 点击超链接后弹出下载提示框
  • 完成图片文件下载

分析

在前端页面点击标签通过href进行获取链接指向的来源。

  • 超链接指向的资源如果能够被浏览器解析,则直接在浏览器中展示

  • 如果不能解析,则弹出下载框

    弹出下载框需要设置content-disposition:

    1
    content-disposition:attachment;filename=xxx

步骤

  • 定义页面,编辑超链接href属性,指向servlet,传递资源名称filename

  • 书写servlet

    1. 获取文件名称
    2. 使用字节输入流加载文件进内存
    3. 指定response的响应头:
    1
    content-disposition:attachment;filename=xxx
        4. 将数据写出到response输出流
    

代码

下载页面download.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>下载</title>
</head>
<body>


<a href="/day15/img/2.jpg">图片</a>
<a href="/day15/img/1.avi">视频</a>
</br>
<a href="/day15/downloadServlet?filename=2.jpg">图片</a>
<a href="/day15/downloadServlet?filename=1.avi">视频</a>
</body>
</html>

DownloadServlet

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
package cn.itcast.web.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;

@WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 使用响应头指定资源打开方式
response.setHeader("content-disposition","attachment;filname=111");
//获取文件名
String fileName = request.getParameter("filename");
//拿到该文件在服务器中的真实路径
ServletContext context = this.getServletContext();
//设置响应内容
response.setContentType(context.getMimeType(fileName));
String path = context.getRealPath("/img/" + fileName);
//将文件放到response的输出流中
//先设置响应类型为文件

//将该文件加载进内存
FileInputStream fis=new FileInputStream(path);
byte[] tmp=new byte[1024*1024];
int len=0;
//将文件放到response的输出流中
while ((len=fis.read(tmp))!=-1){//注意读取到文件的末尾返回值是-1
response.getOutputStream().write(tmp,0,len);//每次从tmp中0开始输出len长度到输出流中去
}
fis.close();



}
}

演示

在这里插入图片描述

项目总结

如何实现下载?

  • 前端是一个超链接a标签,href为文件来源。如果href来源是一个浏览器可以解析的文件,那么浏览器直接打开;如果href来源是一个servlet那么需要servlet对response输出流进行处理。href接受response输出流。
  • servlet的编写
    1. 用content-disposition设置资源打开的方式
    2. 获取传递的参数,通过servletContext获取该文件的mime类型,再通过setContentType设置响应内容
    3. 获取服务器文件的路径(下载是从服务器中下载),api为servletContext.getRealPath
    4. 利用输入流将文件读取进内存,然后再输出到response输出流中。超链接就可以接收到流文件。剩下的工作就是浏览器进行操作。

如何获取服务器文件路径

利用servletContext对象的方法getRealPath进行获取,不同文件位置获取方法参数不一样,如下

  1. 文件在web目录下,参数路径就是文件名

    1
    String b = context.getRealPath("/b.txt");
  2. 文件在WEB-INF目录下,参数路径就是/WEB-INF/文件名

    1
    String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
  3. 文件在src目录下,参数路径就是/WEB-INF/classes/文件名

    1
    String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问

content-disposition 和content-type区别

  • content-disposition告诉浏览器文件的打开方式,一般用附件打开采用content-disposition。

    1
    2
    response.setHeader("content-disposition","attachment;filname=111");

  • content-type告诉浏览器响应的类型,参数一般是mime类型,需要借助servletContext获取对应文件的mime类型。

    1
    response.setContentType(context.getMimeType(fileName));