文件下载编码实现
通过前面的学习,了解了实现文件下载的原理,接下来,本节将通过一个具体的案例,分步骤演示文件下载的实现过程,具体如下:
(1)在chapter06工程下新建一个包cn.itcast.chapter06.example02。
(2)在chapter06工程的WebContent目录下创建下载页面download.jsp。
download.jsp的代码如例1所示。
例11 download.jsp
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
3 "http://www.w3.org/TR/html4/loose.dtd">
4 <html>
5 <head>
6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
7 <title>文件下载</title>
8 </head>
9 <body>
10 <a
11 href="${pagContext.request.contextPath}/chapter06/DownloadServlet"}>
12 文件下载
13 </a>
14 <br />
15 </body>
16 </html>
编写DownloadServlet类,该类主要用于设置所要下载的文件以及文件在浏览器中的打开方式,DownloadServlet具体实现代码如例2所示。
例2 DownloadServlet.java
1 package cn.itcast.chapter06.example02;
2 import java.io.*;
3 import javax.servlet.*;
4 import javax.servlet.http.*;
5 public class DownloadServlet extends HttpServlet {
6 public void doGet(HttpServletRequest request, HttpServletResponse
7 response) throws ServletException, IOException {
8 response.setContentType("text/html;charset=utf-8");
9 // 通知浏览器以下载的方式打开
10 response.addHeader("Content-Type", "application/octet-stream");
11 response.addHeader("Content-Disposition",
12 "attachment;filename=1.jpg");
13 // 通过文件流读取文件
14 InputStream in = getServletContext().getResourceAsStream(
15 "/download/1.jpg");
16 // 获取response对象的输出流
17 OutputStream out = response.getOutputStream();
18 byte[] buffer = new byte[1024];
19 int len;
20 while ((len = in.read(buffer)) != -1) {
21 out.write(buffer, 0, len);
22 }
23 }
24 public void doPost(HttpServletRequest request, HttpServletResponse
25 response) throws ServletException, IOException {
26 doGet(request, response);
27 }
28 }
重启Tomcat服务器,通过浏览器访问地址
http://localhost:8080/chapter06/DownloadServlet
,浏览器的显示界面如图1所示。
图1 DownloadServlet.java
从图2中可以看出,浏览器窗口弹出一个文件下载的对话框,单击该对话框的【保存】按钮即可完成文件的下载。需要注意的是,如果浏览器中安装了某些特殊插件,可能不会弹出文件下载的对话框,而是直接开始下载文件。
在操作服务器中的资源时,资源文件名的中文乱码问题一直是需要解决的问题。这里,如果我们将文件的名称“1.jpg”重命名为“风景.jpg”,通过浏览器再次下载文件,此时浏览器的显示结果如图2所示。
图2 运行结果
从图6-8可以看出,当文件名为中文时,文件下载会出现乱码。由于文件名是通过content-disposition 头字段发送给浏览器的,因此,之前处理消息体乱码的setContentType()方法是无法解决的。
为了解决上述出现的乱码问题,ServletAPI中提供了一个URLEncoder类,该类定义的encode(String s, String enc)方法,可以将URL中的字符串以指定的编码形式输出,通常这种编码方式称为URL编码。HTTP消息头的数据只有经过URL编码成世界通用的符号后,才不会在传输过程中出现乱码问题。
接下来使用URLEncoder类的encode(String s, String enc)方法对例2进行改写,改写后的代码如例3所示。
例3 DownloadServlet.java
1 package cn.itcast.chapter06.example02;
2 import java.io.*;
3 import java.net.URLEncoder;
4 import javax.servlet.*;
5 import javax.servlet.http.*;
6 public class DownloadServlet extends HttpServlet {
7 public void doGet(HttpServletRequest request, HttpServletResponse
8 response) throws ServletException, IOException {
9 response.setContentType("text/html;charset=utf-8");
10 // 获得绝对路径创建文件对象
11 String path=getServletContext()
12 .getRealPath("/download/风景.jpg");
13 File file=new File(path);
14 // 通知浏览器以下载的方式打开文件
15 response.addHeader("Content-Type", "application/octet-stream");
16 response.addHeader("Content-Disposition","attachment;filename="
17 +URLEncoder.encode(file.getName(),"utf-8"));
18 // 通过文件对象获取文件相关的输入流
19 InputStream in=new FileInputStream(file);
20 // 获取response对象的输出流
21 OutputStream out = response.getOutputStream();
22 byte [] buffer=new byte[1024];
23 int len;
24 while((len=in.read(buffer))!=-1){
25 out.write(buffer,0,len);
26 }
27 }
28 public void doPost(HttpServletRequest req, HttpServletResponse resp)
29 throws ServletException, IOException {
30 doGet(req, resp);
31 }
32 }
重启Tomcat服务器,再次访问DownloadServlet,浏览器显示的界面如图3所示。
图3 DownloadServlet.java
从图3可以看出,文件名并没有出现乱码问题,因此,说明使用encode(String s, String enc)方法可以成功地解决文件下载过程中的乱码问题。