文件下载案例--包含三种浏览器下载的工具包

文件下载案例

文件下载的需求

  1. 页面显示超链接
  2. 点击超链接后弹出下载提示框
  3. 完成图片文件的下载

项目分析

  1. 若超链接指向的资源能够被浏览器解析,则在浏览器中显示;若不能解析,则弹出下载提示框
    *不能满足要求,我们需要在任何情况下都弹出下载提示框
  2. 所以我们需要设置资源的打开方式
    *即设置响应头Content-disposition的值为attachment;filename=xxx

步骤

  1. 定义一个html页面,编辑超链接属性,使其指向一个Servlet,并且需要传递下载资源的文件名称filename
    *编写一个download.html页面
	
    <html lang="en">
     <head>
         <meta charset="UTF-8">
         <title>Titletitle>
     head>
     <body>
         <a href="/response/downloadServlet?filename=IDEA.jpg">图片下载a>
     body>
     html>
  1. 定义一个Servlet处理文件的下载
    1. 首先需要获取文件的名称
      *使用request对象获取
      *String filename = request.getParameter(“filename”);
    2. 然后使用字节输入流,将文件加载进内存
      *需要获取文件的真实路径
      ServletContext servletContext = this.getServletContext();
      String realPath = servletContext.getRealPath("/image/"+filename);
      *然后用字节输入流关联该文件
      FileInputStream fileInputStream = new FileInputStream(realPath);
    3. 设置response响应头
      *响应头类型Content-type;告知文件类型
      *所以需要先获取文件类型
      String mimeType = servletContext.getMimeType(filename);
      response.setHeader(“Content-type”, mimeType);
      *响应头的打开方式Content-disposition;设置为文件打开
      response.setHeader(“Content-disposition”, “attachment;filename=”+filename);
    4. 将输入流的数据写出到response输出流(若直接输出,则不一定会弹出下载提示框,所以在此之前要先设置一下响应头)
      1. 首先获取字节输出流
        *ServletOutputStream outputStream = response.getOutputStream();
      2. 然后准备缓存数组
        *byte[] buffer = new byte[1024 * 8];
        *int len = 0;
      3. 然后依次从输入流读取数据到数组
        *while((len = fileInputStream.read(buffer)) != -1){
      4. 将数组中的数据依次写出到response流
        *outputStream.write(buffer, 0, len);
      5. 关闭字节输入流
        *fileInputStream.close();

文件名的乱码问题

  • 若文件名为中文,则不能正确解析
  • 出现原因
    • 在以上步骤中,获取文件名并且将其转化为String时,不同浏览器的版本对中文所做的处理不同
  • 解决方法
    1. 获取浏览器的版本信息
      *获取user-agent请求头
    2. 根据不同的版本信息,分别响应不同的数据(设置文件名的编码方式)

解决浏览器中文乱码问题的工具包

    /**
     * 处理浏览器下的中文问题
     * @param agent      浏览器的版本信息
     * @param filename   文件的名字
     * @return  filename 处理后的文件名
     */
    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")){
            // 火狐浏览器
            filename = new String(filename.getBytes(), "ISO8859-1");
            // Base64.Encoder Base64Encoder = Base64.getEncoder();
            // filename = "=?utf-8?B?" + Base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
        } else{
            // 其他浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }

        return filename;
    }

案例代码

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1.通过request获取文件名称
    String filename = request.getParameter("filename");

    //2.使用字节输入流,将文件加载进内存
    //2.1获取ServletContext对象
    ServletContext servletContext = this.getServletContext();
    //2.2获取文件的服务器路径
    String realPath = servletContext.getRealPath("/image/"+filename);
    //2.3使用字节输入流关联该文件
    FileInputStream fileInputStream = new FileInputStream(realPath);


    //3.设置response响应头
    //3.1获取文件的MIME类型
    String mimeType = servletContext.getMimeType(filename);
    //3.2设置响应头类型Content-type
    response.setHeader("Content-type", mimeType);
    //3.3设置响应头的打开方式Content-disposition
    
    /**
     * 解决中文文件名乱码问题
     */
    // 1.获取user-agent请求头
    String agent = request.getHeader("user-agent");
    // 2.使用DownloadUtils工具类编码文件名
    filename = DownloadUtils.getFileName(agent, filename);

    response.setHeader("Content-disposition", "attachment;filename="+filename);

    //4. 将输入流的数据写出到response输出流
    ServletOutputStream outputStream = response.getOutputStream();
    byte[] buffer = new byte[1024 * 8];
    int len = 0;
    while((len = fileInputStream.read(buffer)) != -1){
        outputStream.write(buffer, 0, len);
    }
    fileInputStream.close();


    }

你可能感兴趣的:(Java-HTTP)