使用HttpServletResponse提供文件下载

文件下载功能是web开发中经常使用到的功能,使用HttpServletResponse对象就可以实现文件的下载

文件下载功能的实现思路:

  1.获取要下载的文件的绝对路径

  2.获取要下载的文件名

  3.设置content-disposition响应头控制浏览器以下载的形式打开文件

  4.获取要下载的文件输入流

  5.创建数据缓冲区

  6.通过response对象获取OutputStream流

  7.将FileInputStream流写入到buffer缓冲区

  8.使用OutputStream将缓冲区的数据输出到客户端浏览器

范例:使用Response实现文件下载

复制代码
 1 package gacl.response.study;
 2 import java.io.FileInputStream;
 3 import java.io.FileNotFoundException;
 4 import java.io.FileReader;
 5 import java.io.IOException;
 6 import java.io.InputStream;
 7 import java.io.OutputStream;
 8 import java.io.PrintWriter;
 9 import java.net.URLEncoder;
10 import javax.servlet.ServletException;
11 import javax.servlet.http.HttpServlet;
12 import javax.servlet.http.HttpServletRequest;
13 import javax.servlet.http.HttpServletResponse;
14 /**
15  * @author gacl
16  * 文件下载
17  */
18 public class ResponseDemo02 extends HttpServlet {
19 
20     public void doGet(HttpServletRequest request, HttpServletResponse response)
21             throws ServletException, IOException {
22         downloadFileByOutputStream(response);//下载文件,通过OutputStream流
23     }
24 
25     /**
26      * 下载文件,通过OutputStream流
27      * @param response
28      * @throws FileNotFoundException
29      * @throws IOException
30      */
31     private void downloadFileByOutputStream(HttpServletResponse response)
32             throws FileNotFoundException, IOException {
33         //1.获取要下载的文件的绝对路径
34         String realPath = this.getServletContext().getRealPath("/download/1.JPG");
35         //2.获取要下载的文件名
36         String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
37         //3.设置content-disposition响应头控制浏览器以下载的形式打开文件
38         response.setHeader("content-disposition", "attachment;filename="+fileName);
39         //4.获取要下载的文件输入流
40         InputStream in = new FileInputStream(realPath);
41         int len = 0;
42         //5.创建数据缓冲区
43         byte[] buffer = new byte[1024];
44         //6.通过response对象获取OutputStream流
45         OutputStream out = response.getOutputStream();
46         //7.将FileInputStream流写入到buffer缓冲区
47         while ((len = in.read(buffer)) > 0) {
48         //8.使用OutputStream将缓冲区的数据输出到客户端浏览器
49             out.write(buffer,0,len);
50         }
51         in.close();
52     }
53 
54     public void doPost(HttpServletRequest request, HttpServletResponse response)
55             throws ServletException, IOException {
56         doGet(request, response);
57     }
58 }
复制代码

运行结果如下所示:

  

 范例:使用Response实现中文文件下载

  下载中文文件时,需要注意的地方就是中文文件名要使用URLEncoder.encode方法进行编码(URLEncoder.encode(fileName, "字符编码")),否则会出现文件名乱码。

复制代码
 1 package gacl.response.study;
 2 import java.io.FileInputStream;
 3 import java.io.FileNotFoundException;
 4 import java.io.FileReader;
 5 import java.io.IOException;
 6 import java.io.InputStream;
 7 import java.io.OutputStream;
 8 import java.io.PrintWriter;
 9 import java.net.URLEncoder;
10 import javax.servlet.ServletException;
11 import javax.servlet.http.HttpServlet;
12 import javax.servlet.http.HttpServletRequest;
13 import javax.servlet.http.HttpServletResponse;
14 /**
15  * @author gacl
16  * 文件下载
17  */
18 public class ResponseDemo02 extends HttpServlet {
19 
20     public void doGet(HttpServletRequest request, HttpServletResponse response)
21             throws ServletException, IOException {
22         downloadChineseFileByOutputStream(response);//下载中文文件
23     }
24 
25     /**
26      * 下载中文文件,中文文件下载时,文件名要经过URL编码,否则会出现文件名乱码
27      * @param response
28      * @throws FileNotFoundException
29      * @throws IOException
30      */
31     private void downloadChineseFileByOutputStream(HttpServletResponse response)
32             throws FileNotFoundException, IOException {
33         String realPath = this.getServletContext().getRealPath("/download/张家界国家森林公园.JPG");//获取要下载的文件的绝对路径
34         String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);//获取要下载的文件名
35         //设置content-disposition响应头控制浏览器以下载的形式打开文件,中文文件名要使用URLEncoder.encode方法进行编码,否则会出现文件名乱码
36         response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));
37         InputStream in = new FileInputStream(realPath);//获取文件输入流
38         int len = 0;
39         byte[] buffer = new byte[1024];
40         OutputStream out = response.getOutputStream();
41         while ((len = in.read(buffer)) > 0) {
42             out.write(buffer,0,len);//将缓冲区的数据输出到客户端浏览器
43         }
44         in.close();
45     }
46     
47     public void doPost(HttpServletRequest request, HttpServletResponse response)
48             throws ServletException, IOException {
49         doGet(request, response);
50     }
51 }
复制代码

运行结果如下所示:

  

  文件下载注意事项:编写文件下载功能时推荐使用OutputStream流,避免使用PrintWriter流,因为OutputStream流是字节流,可以处理任意类型的数据,而PrintWriter流是字符流,只能处理字符数据,如果用字符流处理字节数据,会导致数据丢失。

范例:使用PrintWriter流下载文件

复制代码
 1 package gacl.response.study;
 2 import java.io.FileInputStream;
 3 import java.io.FileNotFoundException;
 4 import java.io.FileReader;
 5 import java.io.IOException;
 6 import java.io.InputStream;
 7 import java.io.OutputStream;
 8 import java.io.PrintWriter;
 9 import java.net.URLEncoder;
10 import javax.servlet.ServletException;
11 import javax.servlet.http.HttpServlet;
12 import javax.servlet.http.HttpServletRequest;
13 import javax.servlet.http.HttpServletResponse;
14 /**
15  * @author gacl
16  * 文件下载
17  */
18 public class ResponseDemo02 extends HttpServlet {
19 
20     public void doGet(HttpServletRequest request, HttpServletResponse response)
21             throws ServletException, IOException {
22         downloadFileByPrintWriter(response);//下载文件,通过PrintWriter流
23     }
24 
25     /**
26      * 下载文件,通过PrintWriter流,虽然也能够实现下载,但是会导致数据丢失,因此不推荐使用PrintWriter流下载文件
27      * @param response
28      * @throws FileNotFoundException
29      * @throws IOException
30      */
31     private void downloadFileByPrintWriter(HttpServletResponse response)
32             throws FileNotFoundException, IOException {
33         String realPath = this.getServletContext().getRealPath("/download/张家界国家森林公园.JPG");//获取要下载的文件的绝对路径
34         String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);//获取要下载的文件名
35         //设置content-disposition响应头控制浏览器以下载的形式打开文件,中文文件名要使用URLEncoder.encode方法进行编码
36         response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));
37         FileReader in = new FileReader(realPath);
38         int len = 0;
39         char[] buffer = new char[1024];
40         PrintWriter out = response.getWriter();
41         while ((len = in.read(buffer)) > 0) {
42             out.write(buffer,0,len);//将缓冲区的数据输出到客户端浏览器
43         }
44         in.close();
45     }
46     
47     public void doPost(HttpServletRequest request, HttpServletResponse response)
48             throws ServletException, IOException {
49         doGet(request, response);
50     }
51 }
复制代码

运行结果如下:

  

正常弹出下载框,此时我们点击【保存】按钮将文件下载下来,如下所示:

  

  可以看到,只下载了5.25MB,而这张图片的原始大小却是

  

  这说明在下载的时候数据丢失了,所以下载不完全,所以这张图片虽然能够正常下载下来,但是却是无法打开的,因为丢失掉了部分数据,如下所示:

  

   所以使用PrintWriter流处理字节数据,会导致数据丢失,这一点千万要注意,因此在编写下载文件功能时,要使用OutputStream流,避免使用PrintWriter流,因为OutputStream流是字节流,可以处理任意类型的数据,而PrintWriter流是字符流,只能处理字符数据,如果用字符流处理字节数据,会导致数据丢失。

展开阅读全文

没有更多推荐了,返回首页