文件下载需求:
1. 页面显示超链接 2. 点击超链接后弹出下载提示框 3. 完成图片文件下载
分析过程:
1. 超链接指向的资源如果能够被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载提示框。不满足需求 2. 任何资源都必须弹出下载提示框 3. 使用响应头设置资源的打开方式: content-disposition:attachment;filename=xxx
步骤:
1. 定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename 2. 定义Servlet 1. 获取文件名称 2. 使用字节输入流加载文件进内存 3. 指定response的响应头: content-disposition:attachment;filename=xxx 4. 将数据写出到response输出流
代码实现:
下载页面:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>文件下载</title> 6 </head> 7 <body> 8 9 10 <a href="/day13/img/狐狸.jpg">图片1</a> 11 12 <a href="/day13/img/2.jpg">图片2</a> 13 14 <a href="/day13/img/1.avi">视频</a> 15 <hr> 16 17 18 <a href="/day13/downloadservlet?filename=狐狸.jpg">图片1</a> 19 20 <a href="/day13/downloadservlet?filename=2.jpg">图片2</a> 21 22 <a href="/day13/downloadservlet?filename=1.avi">视频</a> 23 24 25 26 27 </body> 28 </html>
DownLoadServlet 类
1 import javax.servlet.ServletContext; 2 import javax.servlet.ServletException; 3 import javax.servlet.ServletOutputStream; 4 import javax.servlet.annotation.WebServlet; 5 import javax.servlet.http.HttpServlet; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 import java.io.FileInputStream; 9 import java.io.IOException; 10 11 @WebServlet("/downloadservlet") 12 public class downloadservlet extends HttpServlet { 13 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 14 //1获取请求参数,文件名称 15 String filename = request.getParameter("filename"); 16 17 //2使用字节输入流加载文件进内存 18 // 2.1 找文件服务器路径 19 ServletContext servletContext = this.getServletContext(); 20 String realPath = servletContext.getRealPath("/img/" + filename); 21 22 //2.2 使用字节流关联 23 FileInputStream fis = new FileInputStream(realPath); 24 25 //3 设置 response 的响应头 26 // 3.1 设置响应头类型:content-type 27 String mimeType = servletContext.getMimeType(filename); 28 response.setHeader("content-type",mimeType); 29 // 3.2 设置响应头打开方式:content-disposition 30 31 response.setHeader("content-disposition","attachment;filename="+filename); 32 33 34 // 4. 将输入流的数据写出到输出流中 35 ServletOutputStream sos = response.getOutputStream(); 36 37 byte[] buff = new byte[1024*8]; 38 int len = 0; 39 40 while((len = fis.read(buff)) != -1) { 41 sos.write(buff,0,buff.length); 42 } 43 44 // 关闭流对象 45 fis.close(); 46 } 47 48 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 49 this.doPost(request, response); 50 } 51 }
上面的案例中发现,当下载的文件名字是中文的时候,下载的时候会出现乱码。
文件名中文乱码问题
解决思路:
(1)获取客户端使用的浏览器版本信息
(2)根据不同的版本信息,设置 filename 的编码方式不同
编码工具类:
使用 Base64 编码,需要导入 commons-codec-1.13.jar 包。
1 package cn.itcast.download; 2 3 4 import org.apache.commons.codec.binary.Base64; 5 6 import java.io.UnsupportedEncodingException; 7 import java.net.URLEncoder; 8 9 10 public class DownLoadUtils { 11 12 public static String getFileName(String agent, String filename) throws UnsupportedEncodingException { 13 if (agent.contains("MSIE")) { 14 // IE浏览器 15 filename = URLEncoder.encode(filename, "utf-8"); 16 filename = filename.replace("+", " "); 17 } else if (agent.contains("Firefox")) { 18 Base64 base64Encoder = new Base64(); 19 // 火狐浏览器 20 //BASE64Encoder base64Encoder = new BASE64Encoder(); 21 filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; 22 } else { 23 // 其它浏览器 24 filename = URLEncoder.encode(filename, "utf-8"); 25 } 26 return filename; 27 } 28 }
DownLoadServlet 类(改进):
1 package cn.itcast.download; 2 3 import javax.servlet.ServletContext; 4 import javax.servlet.ServletException; 5 import javax.servlet.ServletOutputStream; 6 import javax.servlet.annotation.WebServlet; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 import java.io.FileInputStream; 11 import java.io.IOException; 12 13 @WebServlet("/downloadservlet") 14 public class downloadservlet extends HttpServlet { 15 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 16 //1获取请求参数,文件名称 17 String filename = request.getParameter("filename"); 18 19 //2使用字节输入流加载文件进内存 20 // 2.1 找文件服务器路径 21 ServletContext servletContext = this.getServletContext(); 22 String realPath = servletContext.getRealPath("/img/" + filename); 23 24 //2.2 使用字节流关联 25 FileInputStream fis = new FileInputStream(realPath); 26 27 //3 设置 response 的响应头 28 // 3.1 设置响应头类型:content-type 29 String mimeType = servletContext.getMimeType(filename); 30 response.setHeader("content-type",mimeType); 31 // 3.2 设置响应头打开方式:content-disposition 32 33 // 3.3 解决中文文件名问题 34 // 1 获取 user-agent 请求头 35 String agent = request.getHeader("user-agent"); 36 // 2 使用工具类方法编码文件即可 37 filename = DownLoadUtils.getFileName(agent, filename); 38 39 response.setHeader("content-disposition","attachment;filename="+filename); 40 41 42 // 4. 将输入流的数据写出到输出流中 43 ServletOutputStream sos = response.getOutputStream(); 44 45 byte[] buff = new byte[1024*8]; 46 int len = 0; 47 48 while((len = fis.read(buff)) != -1) { 49 sos.write(buff,0,buff.length); 50 } 51 52 // 关闭流对象 53 fis.close(); 54 } 55 56 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 57 this.doPost(request, response); 58 } 59 }
原文地址:https://www.cnblogs.com/niujifei/p/11621866.html
时间: 2024-11-05 16:20:55