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