03010_案例:完成文件下载

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不能同时调用。

  

  

posted @ 2018-01-05 14:33  gzdlh  阅读(166)  评论(0编辑  收藏  举报