案例:

  • 文件下载需求:
    1. 页面显示超链接
    2. 点击超链接后弹出下载提示框
    3. 完成图片文件下载
  • 分析:
    1. 超链接指向的资源如果能够被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载提示框,不满足需求
    2. 需求:任何资源都必须弹出下载提示框
    3. 解决方式:使用响应头设置资源的打开方式:
      • content-disposition:attachment;filename=xxx
  • 步骤:
    1. 定义页面,编辑超链接 href 属性,指向 Servlet, 传递资源名称 filename
    2. 定义 Servlet
      1. 获取文件名称
      2. 使用字节输入流加载文件进内存
      3. 指定 response 的响应头:content-dispostion:attchment;filename=xxx
      4. 将数据写出到 response 输出流

案例代码:

  • HttpServlet 类
@WebServlet("/servletload")
public class Servletload extends HttpServlet {
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //1. 获取请求参数,文件名称
        String file = req.getParameter("filename");
        //2. 使用字节输入流加载文件进内存
        //2.1 找到文件服务器路径,ServletContext: 代表整个 web 应用,可以对服务器通信
        ServletContext context = this.getServletContext();
        //realpath: 获取文件服务器路径:/opt/idea/ideaDemo/day12_1/out/artifacts/day12_1_war_exploded/image/tupian.jpg
        String filerealpath = context.getRealPath("/image/"+file);
        System.out.println(filerealpath);
        //2.2 使用字节流关联
        FileInputStream input = new FileInputStream(filerealpath);
        //3. 设置 response 的响应头
        //3.1 获取 MIME 类型
        String mime = context.getMimeType(file);
        //3.2 设置响应头类型 content-type: 服务器告诉客户端本次响应体格式以及编码
        resp.setHeader("content-type",mime);
        // 解决中文文件名乱码问题
        //1. 获取 user-agent 请求头 user-agent: 浏览器告诉服务器访问时使用的浏览器版本信息,可以解决浏览器的兼容性问题
        String user_agent = req.getHeader("user-agent");
        //2. 使用工具类编码即可
        file = DownLoadUtils.getFileName(user_agent,file);
        //3.3 设置响应头打开方式
        resp.setHeader("content-disposition","attachment;filename="+"/image/"+file);
        //4. 将输入流的数据写出到输出流中
        ServletOutputStream out = resp.getOutputStream();
        int i = 0;
        byte[] by = new byte[1024 * 8];
        while((i = input.read(by)) != -1){
            out.write(by,0,i);
        }
        // 关闭流
        input.close();
        out.close();
    }
    protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws IOException {
        this.doPost(req,resp);
        int i = 0;
    }
}
  • Html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="/dkx/image/风景.jpg">图片</a>
<hr>
<a href="/dkx/servletload?filename=风景.jpg">图片1</a>
</body>
</html>
  • 解决中文乱码问题

需要使用到 BASE64Encoder.jar 包来对火狐浏览器进行编码的处理

public class DownLoadUtils {
    public static String getFileName(String agent,String filename) throws UnsupportedEncodingException {
        if(agent.contains("MSIE")){
            //IE 浏览器
            filename = URLEncoder.encode(filename,"utf-8");
            filename = filename.replace("+"," ");
        }else if(agent.contains("Firefox")){
            // 火狐浏览器
            BASE64Encoder base64encoder = new BASE64Encoder();
            filename = "?utf-8?B?" + base64encoder.encode(filename.getBytes("utf-8"))+"?=";
        }else{
            // 其它浏览器
            filename = URLEncoder.encode(filename,"utf-8");
        }
        return filename;
    }
}