文件的下载
情景:在一些网络系统中,需要隐藏下载文件的真实地址,或者下载的文件需要一个程序来动态的确定后在传送给客户端
方案:利用程序编码实现下载
可以增加安全访问控制,只对经过授权认证的用户提供下载
可以从任意位置提供下载的数据
利用程序实现下载需要设置 2 个报头:
Web 服务器需要告诉浏览器其所输出的内容的类型不是普通的文本文件或 HTML 文件,而是一个要保存到本地的下载文件。设置Content-Type 的值为:application/x-msdownload
Web 服务器希望浏览器不直接处理相应的实体内容,而是由用户选择将相应的实体内容保存到一个文件中,这需要设置 Content-Disposition 报头。该报头指定了接收程序处理数据内容的方式,在 HTTP 应用中只有 attachment 是标准方式,attachment 表示要求用户干预。在 attachment 后面还可以指定 filename 参数,该参数是服务器建议浏览器将实体内容保存到文件中的文件名称。在设置 Content-Dispostion 之前一定要指定 Content-Type.
response.setContentType("application/x-msdownload");
String fileName = "data.pdf";
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
因为要下载的文件可以是各种类型的文件,所以要将文件传送给客户端,其相应内容应该被当做二进制来处理,所以应该调用response.getOutputStream()方法返回 ServeltOutputStream 对象来向客户端写入文件内容。
OutputStream out = response.getOutputStream();
InputStream in = getServletContext().getResourceAsStream("/download/data.pdf");
byte [] buffer = new byte[1024];
int len = 0;
while((len = in.read(buffer)) != -1){
out.write(buffer, 0, len);
}
in.close();
示例
三种方式:
1. 静态下载
2. jsp 动态下载
3. servlet 动态下载
文件目录:
src
| - org.rabbitx.web.javaweb.download
| - DownloadServlet
WebContent
| - download
| - download.jsp
| - test.jsp
| - data.pdf
| - WEB-INF
| - web.xml
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Download Demo</title> </head> <body> <!-- 静态下载 --> <a href="data.pdf">Download[Tag A]</a><br> <!-- jsp 动态下载 --> <a href="test.jsp">Download[Jsp]</a><br> <!-- servlet 动态下载 --> <a href="${pageContext.request.contextPath}/servlet/download">Download[Servlet]</a><br> </body> </html>
<%@page import="java.util.Date"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Test Page</title> </head> <body> <!-- 以下载的方式获取本页面内容,把本页面内容生成后,以下载文件的方式提供给用户 --> <h4>Test Page</h4> Time: <%= new Date() %> <% //1. 通知客户端浏览器: 这是一个需要下载的文件, 不能再按普通的 html 的方式打开. // 即设置一个响应的类型: application/x-msdownload response.setContentType("application/x-msdownload"); //2. 通知客户端浏览器: 不再由浏览器来处理该文件, 而是交由用户自行处理 // 设置用户处理的方式: 响应头: Content-Disposition response.setHeader("Content-Disposition", "attachment;filename=test.jsp.txt"); %> </body> </html>
package org.rabbitx.web.javaweb.download;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = -2017813047026703175L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/x-msdownload");
String fileName = "data.pdf";
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
OutputStream out = response.getOutputStream();
InputStream in = getServletContext().getResourceAsStream("/download/data.pdf");
byte [] buffer = new byte[1024];
int len = 0;
while((len = in.read(buffer)) != -1){
out.write(buffer, 0, len);
}
in.close();
//out由容器管理,不需要关闭
}
}
<servlet> <servlet-name>downloadServlet</servlet-name> <servlet-class>org.rabbitx.web.javaweb.download.DownloadServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>downloadServlet</servlet-name> <url-pattern>/servlet/download</url-pattern> </servlet-mapping>
测试:http://localhost:8080/org.rabbitx.web.javaweb/download/download.jsp