一、文件下载概述
比如图片或者HTML这类静态资源,仅仅要在浏览器中打开正确的网址就行下载。仅仅要资源放在应用程序文件夹或者其下的子文件夹中,但不在WEB-INF下。Servlet/JSP容器就会将资源发送到浏览器。
但有的时候,静态资源被保存在应用程序文件夹之外,或者保存在数据库中。或者有时候你须要控制让某些人可以看到这个资源,同一时候又要防止其它站点引用它。每当遇到这类情况时,就必须通过编程来发送资源。
通过编程的方式实现文件下载但是让我们有选择的将一个文件发送到浏览器。
为了将资源比方文件发送到浏览器,须要在Servlet中完毕下面工作。这里说明下面。一般不用JSP页面。由于要发送的是浏览器不会显示的二进制代码。
1.将响应内容类型设置为“文件”的内容类型。
标头Content-Type用来规定实体主体中的数据类型,包括“媒体类型”和“子类型标示符”。假设希望浏览器总是显示为“Save as”对话框时,就将内容类型设置为:application/octetstream。
2.加入一个名为content-disposition的HTTP响应标头。
给上述响应标头赋值:attachment;filename="XXX"。这里的XXX是在文件下载对话框中显示的默认文件名称。
他能够与真实的文件名称同样,也能够不同。
以下是一个文件下载的实例概述:
response.setContentType(contenttype); FileInputStream fis=new FileInputStream(file); BufferedInputStream bis=new BufferedInputStream(fis); byte[] bytes=new byte[1024]; OutputStream os=response.getOutputStream(); bis.read(bytes); os.write(bytes);
首先,将要下载的文件当成一个FileInputStream,并将内容加入到一个字节数组中。
然后获取HttpServletResponse的OutputStream。并调用它的write()方法。将字节数组传递给它。
二、下载隐藏文件实例
在以下这个演示样例中,secret.pdf文件放在WEB-INF/data里。不同意直接訪问。用一个FileDownloadServlet将secret.pdf文件发送到浏览器,可是授权用户才干浏览。假设用户没有登录。应用程序就会跳转到login界面,这里,用户能够在表单中输入username和password,这些内容都被提交到还有一个LoginServlet处理。
以下是该应用程序的结构图:
1.用户提交登录表单
login.jsp页面,包括一个HTML表单,当中有两个输入域:userName和password
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!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=ISO-8859-1"> <title>Login</title> </head> <body> <form action="login" method="post"> <table> <tr> <td>User Name:</td> <td><input type="text" name="userName"/></td> </tr> <tr> <td>PassWord:</td> <td><input type="password" name="password"/></td> </tr> <tr> <td colspan="2"><input type="submit" value="login"/></td> </tr> </table> </form> </body> </html>
提交表单时会调用LoginServlet。它的类代码例如以下。
在这个应用程序中,我如果username与password必须是ken/secret。
package filedownload; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * Servlet implementation class LoginServlet */ public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public LoginServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String username=request.getParameter("userName"); String password=request.getParameter("password"); if(username!=null&&username.equals("ken")&&password!=null&&password.equals("secret")){ HttpSession session=request.getSession(true); session.setAttribute("loggedIn", Boolean.TRUE); response.sendRedirect("download"); //must call return or else the code after this if //block,if any,will be executed return; }else{ RequestDispatcher dispatcher=request.getRequestDispatcher("/login.jsp"); dispatcher.forward(request, response); } } }<span style="font-size:14px;"> </span>
用户登录成功后,会设置一个loggedln会话属性,并将用户转到FileDownloadServlet。
在HttpServletResponse.sendRedirect之后。必须返回,以防止运行后面的代码行。登录失败后,则会将用户转到login.jsp页面。
2.进行文件下载
FileDownloadServlet展示了一个负责发送secret.pdf文件的Servlet。仅仅有当用户的HttpSession中包括loggedlin属性时,表示用户已经成功登录,此时才同意訪问。
package filedownload; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * Servlet implementation class FileDownloadServlet */ public class FileDownloadServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public FileDownloadServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub HttpSession session=request.getSession(); if(session==null||session.getAttribute("loggedIn")==null){ RequestDispatcher dispatcher=request.getRequestDispatcher("/login.jsp"); dispatcher.forward(request, response); return;//must return after dispatcher.forward(),Otherwise the code below will be executed } String dataDirectory =request.getServletContext().getRealPath("/WEB-INF/data/secret.pdf"); //System.out.println(dataDirectory); File file=new File(dataDirectory); if(file.exists()){ response.setContentType("application/pdf"); response.addHeader("Content-Disposition", "attachment;filename=secret.pdf"); byte[] buffer=new byte[1024]; FileInputStream fis=null; BufferedInputStream bis=null; try{ fis=new FileInputStream(file); bis=new BufferedInputStream(fis); OutputStream os=response.getOutputStream(); int i=bis.read(buffer); while(i!=-1){ os.write(buffer,0,i); i=bis.read(buffer); } }catch(IOException e){ System.out.println(e.toString()); }finally{ if(bis!=null){ bis.close(); } if(fis!=null){ fis.close(); } } }else{ System.out.println("secret.pdf does not exit!"); } } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub } }
doGet方法会检查HttpSession中是否有loggedIn属性。
假设没有,则会将用户带到登录界面。
HttpSession session=request.getSession(); if(session==null||session.getAttribute("loggedIn")==null){ RequestDispatcher dispatcher=request.getRequestDispatcher("/login.jsp"); dispatcher.forward(request, response); return;//must return after dispatcher.forward(),Otherwise the code below will be executed }
注意。在RequestDispatcher中调用forward会将控制权转移到不同的资源。可是,它不会中止当前在调用对象的代码运行,因此。跳转之后必须返回。
假设用户已经登录成功。doGet方法就会打开索要的资源,并将它引到ServletResponse的OutputStream。
String dataDirectory =request.getServletContext().getRealPath("/WEB-INF/data/secret.pdf"); //System.out.println(dataDirectory); File file=new File(dataDirectory); if(file.exists()){ response.setContentType("application/pdf"); response.addHeader("Content-Disposition", "attachment;filename=secret.pdf"); byte[] buffer=new byte[1024]; FileInputStream fis=null; BufferedInputStream bis=null; try{ fis=new FileInputStream(file); bis=new BufferedInputStream(fis); OutputStream os=response.getOutputStream(); int i=bis.read(buffer); while(i!=-1){ os.write(buffer,0,i); i=bis.read(buffer); } }catch(IOException e){ System.out.println(e.toString()); }finally{ if(bis!=null){ bis.close(); } if(fis!=null){ fis.close(); } } }else{ System.out.println("secret.pdf does not exit!"); }
利用以下的URL调用FileDownloadServlet,能够对该应用程序进行測试:
http://localhost:8080/app12a/download
3.PS:web.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>app12a</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <servlet> <description></description> <display-name>FileDownloadServlet</display-name> <servlet-name>FileDownloadServlet</servlet-name> <servlet-class>filedownload.FileDownloadServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>FileDownloadServlet</servlet-name> <url-pattern>/download</url-pattern> </servlet-mapping> <servlet> <description></description> <display-name>LoginServlet</display-name> <servlet-name>LoginServlet</servlet-name> <servlet-class>filedownload.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/login</url-pattern> </servlet-mapping> </web-app>
4.測试截图
摘录自:《Servlet和JSP学习指南》