1、什么情况下会文件下载?
浏览器不能解析的文件就下载;
2、什么情况下需要在服务器编写文件下载的代码?
(1)理论上,浏览器可以解析的代码需要编写文件下载代码;
(2)实际开发中,只要是下载文件都编写文件下载代码。
3、文件下载的实质就是文件拷贝,将文件从服务器端拷贝到浏览器端。所以文件下载需要IO技术将服务器端的文件使用InputStream读取到,在使用ServletOutputStream写到response缓冲区中。
4、需要设置两个响应头,告知浏览器文件的类型和文件的打开方式
(1)告知浏览器文件的类型:response.setContentType(文件的MIME类型); ;
(2)告示浏览器文件的打开方式是下载
response.setHeader("Content-Disposition","attachment;filename=文件名称");
(3)download.html
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Insert title here</title> 6 </head> 7 <body> 8 <h1>使用服务器端编码的方式实现文件下载</h1> 9 <a href="/WEB13/downloadServlet?filename=a.flv">a.flv</a> 10 <br /> 11 <a href="/WEB13/downloadServlet?filename=a.jpg">a.jpg</a> 12 <br /> 13 <a href="/WEB13/downloadServlet?filename=a.mp3">a.mp3</a> 14 <br /> 15 <a href="/WEB13/downloadServlet?filename=a.mp4">a.mp4</a> 16 <br /> 17 <a href="/WEB13/downloadServlet?filename=a.txt">a.txt</a> 18 <br /> 19 <a href="/WEB13/downloadServlet?filename=a.zip">a.zip</a> 20 <br /> 21 </body> 22 </html>
(4)DownloadServlet.java
1 package com.gzdlh.contex; 2 3 import java.io.FileInputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 7 import javax.servlet.ServletException; 8 import javax.servlet.ServletOutputStream; 9 import javax.servlet.http.HttpServlet; 10 import javax.servlet.http.HttpServletRequest; 11 import javax.servlet.http.HttpServletResponse; 12 13 public class DownloadServlet extends HttpServlet { 14 15 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 16 // 获得要下载的文件的名称 17 String filename = request.getParameter("filename"); 18 19 // 要下载的这个文件的类型---客户端通过文件的MIME类型取区分类型 20 response.setContentType(this.getServletContext().getMimeType(filename)); 21 22 // 告诉客户端,该文件不是直接解析,而是以附件形式打开(下载) 23 response.setHeader("Content-Disposition", "attachment;filename=" + filename); 24 25 // 获取文件的绝对路径 26 String path = this.getServletContext().getRealPath("download/" + filename); 27 28 // 获得该文件的输入流 29 InputStream in = new FileInputStream(path); 30 31 // 获得输出流---通过response获得的输出流,用于向客户端写内容 32 ServletOutputStream out = response.getOutputStream(); 33 34 // 文件拷贝的模板代码 35 int len = 0; 36 byte[] buffer = new byte[1024]; 37 while ((len = in.read(buffer)) > 0) { 38 out.write(buffer, 0, len); 39 } 40 in.close(); 41 out.close(); 42 } 43 44 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 45 doGet(request, response); 46 } 47 }
5、文件下载的文件名中文乱码
1 if (agent.contains("MSIE")) { 2 // IE浏览器 3 filename = URLEncoder.encode(filename, "utf-8"); 4 filename = filename.replace("+", " "); 5 } else if (agent.contains("Firefox")) { 6 // 火狐浏览器 7 BASE64Encoder base64Encoder = new BASE64Encoder(); 8 filename = "=?utf-8?B?" 9 + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; 10 } else { 11 // 其它浏览器 12 filename = URLEncoder.encode(filename, "utf-8"); 13 } 14 15 其中agent就是请求头User-Agent的值
如,
<a href="/WEB13/downLoadServlet2?filename=美女.jpg">美女.jpg</a>
DownLoadServlet2.java
1 package com.gzdlh.contex; 2 3 import java.io.FileInputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.net.URLEncoder; 7 8 import javax.servlet.ServletException; 9 import javax.servlet.ServletOutputStream; 10 import javax.servlet.http.HttpServlet; 11 import javax.servlet.http.HttpServletRequest; 12 import javax.servlet.http.HttpServletResponse; 13 14 import sun.misc.BASE64Encoder; 15 16 public class DownLoadServlet2 extends HttpServlet { 17 18 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 19 20 // 文件名是中文名 21 22 // 获得要下载的文件的名称 23 String filename = request.getParameter("filename");// ???.jpg 24 // 解决获得中文参数的乱码 25 filename = new String(filename.getBytes("ISO8859-1"), "UTF-8");// 美女.jpg 26 27 // 获得请求头中的User-Agent 28 String agent = request.getHeader("user-Agent"); 29 30 // 根据就不同浏览器进行不同的编码 31 String filenameEncoder = ""; 32 if (agent.contains("MSIE")) { 33 // IE浏览器 34 filenameEncoder = URLEncoder.encode(filename, "utf-8"); 35 filenameEncoder = filenameEncoder.replace("+", " "); 36 } else if (agent.contains("Firefox")) { 37 // 火狐浏览器 38 BASE64Encoder base64Encoder = new BASE64Encoder(); 39 filenameEncoder = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; 40 } else { 41 // 其它浏览器 42 filenameEncoder = URLEncoder.encode(filename, "utf-8"); 43 } 44 45 // 要下载的这个文件的类型---客户端通过文件的MIME类型取区分类型 46 response.setContentType(this.getServletContext().getMimeType(filename)); 47 48 // 告诉客户端,该文件不是直接解析,而是以附件形式打开(下载)------filename="+filename 客户端默认对名字进行解码 49 response.setHeader("Content-Disposition", "attachment;filename=" + filenameEncoder); 50 51 // 获取文件的绝对路径 52 String path = this.getServletContext().getRealPath("download/" + filename); 53 54 // 获得该文件的输入流 55 InputStream in = new FileInputStream(path); 56 57 // 获得输出流---通过response获得的输出流,用于向客户端写内容 58 ServletOutputStream out = response.getOutputStream(); 59 60 // 文件拷贝的模板代码 61 int len = 0; 62 byte[] buffer = new byte[1024]; 63 while ((len = in.read(buffer)) > 0) { 64 out.write(buffer, 0, len); 65 } 66 in.close(); 67 out.close(); 68 } 69 70 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 71 doGet(request, response); 72 } 73 }
运行结果:
6、response细节点
(1)response获得的流不需要手动关闭,Tomcat容器会帮助我们关闭;
(2)getWriter和getOutputStream不能同时调用。