一、文件下载概述

比如图片或者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学习指南》

Servlet学习笔记(八)—— 文件下载的更多相关文章

  1. python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑

    python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件?当我们点开下载页时, 一般 ...

  2. Learning ROS forRobotics Programming Second Edition学习笔记(八)indigo rviz gazebo

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS forRobotics Pro ...

  3. Go语言学习笔记八: 数组

    Go语言学习笔记八: 数组 数组地球人都知道.所以只说说Go语言的特殊(奇葩)写法. 我一直在想一个人参与了两种语言的设计,但是最后两种语言的语法差异这么大.这是自己否定自己么,为什么不与之前统一一下 ...

  4. 【opencv学习笔记八】创建TrackBar轨迹条

    createTrackbar这个函数我们以后会经常用到,它创建一个可以调整数值的轨迹条,并将轨迹条附加到指定的窗口上,使用起来很方便.首先大家要记住,它往往会和一个回调函数配合起来使用.先看下他的函数 ...

  5. # jsp及servlet学习笔记

    目录 jsp及servlet学习笔记 JSP(Java Server Page Java服务端网页) 指令和动作: servlet(小服务程序) jsp及servlet学习笔记 JSP(Java Se ...

  6. go微服务框架kratos学习笔记八 (kratos的依赖注入)

    目录 go微服务框架kratos学习笔记八(kratos的依赖注入) 什么是依赖注入 google wire kratos中的wire Providers injector(注入器) Binding ...

  7. Servlet学习笔记(四)

    目录 Servlet学习笔记(四) 一.会话技术Cookie.session 1. 什么是会话技术? 2. 会话技术有什么用? 3. Cookie 3.1 什么是Cookie? 3.2 使用Cooki ...

  8. Servlet学习笔记(三)

    目录 Servlet学习笔记(三) 一.HTTP协议 1.请求:客户端发送欸服务器端的数据 2.响应:服务器端发送给客户端的数据 3.响应状态码 二.Response对象 1.Response设置响应 ...

  9. Servlet学习笔记(二)

    目录 Servlet学习笔记(二) Request对象 1.request和response对象: 2.request对象继承体系结构: 3.什么是HttpServletRequest ? 4.Htt ...

  10. Redis学习笔记八:集群模式

    作者:Grey 原文地址:Redis学习笔记八:集群模式 前面提到的Redis学习笔记七:主从复制和哨兵只能解决Redis的单点压力大和单点故障问题,接下来要讲的Redis Cluster模式,主要是 ...

随机推荐

  1. 使用Intellij IDEA的Bookmarks

    用idea的时候,无意中发现了了一个小功能,叫做BookMark Ctrl+F11按出来的然后去查阅了一下文档,主要功能也就是可以清晰的看到自己标的书签附近的代码,比如我们在第11行按一下F11插入一 ...

  2. 边框带阴影 box-shadow

    .chosen-container-active .chosen-single { border: 1px solid #5897fb; -webkit-box-shadow: 0 0 5px rgb ...

  3. _bbox_pred函数

    fast中的_bbox_pred函数和faster中的bbox_transform_inv是一样的,是将框进行4个坐标变换得到新的框坐标.fast中是将selective search生成的框坐标进行 ...

  4. 04XML CSS

    XML CSS 1. XML CSS <?xml-stylesheet  href ="样式表的URI"  type= "text/css" ?> ...

  5. 第3节 hive高级用法:15、hive的数据存储格式介绍

    hive当中的数据存储格式: 行式存储:textFile sequenceFile 都是行式存储 列式存储:orc parquet 可以使我们的数据压缩的更小,压缩的更快 数据查询的时候尽量不要用se ...

  6. PageOffice NET MVC下使用

    1)下载官方demo http://www.zhuozhengsoft.com/dowm/ 2)选择此项下载 3)官方demo暂时还未修改支持42版本以上的谷歌浏览器 所以需要修改以下部分 /home ...

  7. IIS部署SSL证书后提示不可信的解决方案

    IIS部署SSL证书后提示不可信的解决方案   本帖最后由 wosign-support3 于 2015-7-17 17:18 编辑 第一步:打开mmc——点击文件——添加删除管理单元——证书——计算 ...

  8. sphinx配置

    配置文件 ## 数据源src1 source src1 { ## 说明数据源的类型.数据源的类型可以是:mysql,pgsql,mssql,xmlpipe,odbc,python ## 有人会奇怪,p ...

  9. Python中接收用户的输入

    一.如何去接收用户的输入?使用函数 input() 函数 input() 让程序暂停运行,等待用户输入一些文本,获取用户的输入后,Python将其存储到一个变量中,以方便后期使用. name = in ...

  10. AutoMapper 使用总结1

    初识AutoMapper 在开始本篇文章之前,先来思考一个问题:一个项目分多层架构,如显示层.业务逻辑层.服务层.数据访问层.层与层访问需要数据载体,也就是类.如果多层通用一个类,一则会暴露出每层的字 ...