Servlet 笔记 —— ServletContext与文件下载

ServletContext

  1. 概念:代表整个web应用的上下文

  2. 功能

    1. 获取MIME类型

      1. MIME:互联网通信过程中定义的文件数据类型

        1. 格式:大类型/小类型

          比如 text/html image/jpeg

      2. 获取:String getMimeType(String file)

    2. 作为域对象,共享数据

      1. getAttribute(String name,Object value)
      2. setAttribute(String name,Object value)
      3. removeAttribute(String name)

      ServletContext的作用范围:整个web应用

    3. 获取文件的真实路径(服务器路径)

      1. String getRealPath(String path)

      可用于在程序中加载项目中的某个文件(一般是配置文件)

  3. 获取

    1. 通过request对象获取

      request.getServletContext();
      
    2. 通过HttpServlet获取

      //在一个HttpServlet类中
      this.getServletContext();
      

案例:文件下载

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

分析:

  1. 超链接指向的资源,如果能够被浏览器解析,如图片,则直接会在浏览器中展示,不能被浏览器解析的才会提示下载。所以直接用超链接指向资源文件,不满足需求
  2. 使用响应头,设置Content-disposition:attachment;filename=xx

实现步骤:

  1. 编辑超链接,让其href指向一个servlet,传递资源名称
  2. 编写Servlet
    1. 获取文件名称
    2. 找到对应文件,使用字节输入流加载到内存中
    3. 指定response的响应头Content-disposition
    4. 将数据写到response输出流

代码展示:

html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <!-- 浏览器能展示的资源,会直接展示 -->
    <a href="/download?filename=达不溜.jpeg">AW</a>
    <br>
    <!-- 像视频这样,浏览器无法解析
    经测试,IE浏览器中,点击此超链接,会提示下载mp4文件
    Chrome中,点击超链接,会直接打开mp4文件,在Chrome中直接播放
    -->
    <a href="/download?filename=my_first_vlog.mp4">vlog</a>
</body>
</html>

其中的资源文件放在了/web/resources目录下
在这里插入图片描述

Servlet处理逻辑

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

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

		ServletContext context = getServletContext();
		//获取文件,加载到内存中
		request.setCharacterEncoding("utf-8");
		String filename = request.getParameter("filename");
		//给文件名添加路径 /resources  ,默认把资源文件都放resources下
		filename = "/resources/" + filename;
		//获取文件真实路径
		String path = context.getRealPath(filename);
		FileInputStream inputStream = new FileInputStream(path);

		//设置response的响应头,设置content-type和content-disposition
		//表明响应体中的数据是什么MIME类型
		response.setContentType(context.getMimeType(filename));
		//表明以附件形式下载响应体数据

		//解决中文文件名问题
		// 1. 获取user-agent请求头
		// 2. 使用DownloadUtil工具类编码文件名
		String userAgent = request.getHeader("user-agent");
		filename = DownloadUtil.getFileName(userAgent,filename);

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


		//输出到response的流
		ServletOutputStream outputStream = response.getOutputStream();
		byte[] bytes = new byte[1024];
		int len = 0;
		while ((len = inputStream.read(bytes)) != -1){
    
    
			outputStream.write(bytes);
		}

		inputStream.close();
	}
}

其中DownloadUtil用于解决不同浏览器对中文文件名支持不友好的情况

import sun.misc.BASE64Encoder;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

/**
 * 下载工具类
 * 用于解决下载时显示的中文文件名称的问题
 * */
public class DownloadUtil {
    
    
	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;
	}
}

效果展示
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/vcj1009784814/article/details/106083916