文件下载案例
文件下载的需求
- 页面显示超链接
- 点击超链接后弹出下载提示框
- 完成图片文件的下载
项目分析
- 若超链接指向的资源能够被浏览器解析,则在浏览器中显示;若不能解析,则弹出下载提示框
*不能满足要求,我们需要在任何情况下都弹出下载提示框
- 所以我们需要设置资源的打开方式
*即设置响应头Content-disposition的值为attachment;filename=xxx
步骤
- 定义一个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>
- 定义一个Servlet处理文件的下载
- 首先需要获取文件的名称
*使用request对象获取
*String filename = request.getParameter(“filename”);
- 然后使用字节输入流,将文件加载进内存
*需要获取文件的真实路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/image/"+filename);
*然后用字节输入流关联该文件
FileInputStream fileInputStream = new FileInputStream(realPath);
- 设置response响应头
*响应头类型Content-type;告知文件类型
*所以需要先获取文件类型
String mimeType = servletContext.getMimeType(filename);
response.setHeader(“Content-type”, mimeType);
*响应头的打开方式Content-disposition;设置为文件打开
response.setHeader(“Content-disposition”, “attachment;filename=”+filename);
- 将输入流的数据写出到response输出流(若直接输出,则不一定会弹出下载提示框,所以在此之前要先设置一下响应头)
- 首先获取字节输出流
*ServletOutputStream outputStream = response.getOutputStream();
- 然后准备缓存数组
*byte[] buffer = new byte[1024 * 8];
*int len = 0;
- 然后依次从输入流读取数据到数组
*while((len = fileInputStream.read(buffer)) != -1){
- 将数组中的数据依次写出到response流
*outputStream.write(buffer, 0, len);
- 关闭字节输入流
*fileInputStream.close();
文件名的乱码问题
- 若文件名为中文,则不能正确解析
- 出现原因
- 在以上步骤中,获取文件名并且将其转化为String时,不同浏览器的版本对中文所做的处理不同
- 解决方法
- 获取浏览器的版本信息
*获取user-agent请求头
- 根据不同的版本信息,分别响应不同的数据(设置文件名的编码方式)
解决浏览器中文乱码问题的工具包
public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
if (agent.contains("MSIE")){
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")){
filename = new String(filename.getBytes(), "ISO8859-1");
} else{
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
案例代码
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String filename = request.getParameter("filename");
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/image/"+filename);
FileInputStream fileInputStream = new FileInputStream(realPath);
String mimeType = servletContext.getMimeType(filename);
response.setHeader("Content-type", mimeType);
String agent = request.getHeader("user-agent");
filename = DownloadUtils.getFileName(agent, filename);
response.setHeader("Content-disposition", "attachment;filename="+filename);
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();
}