一、文件下载概述

比如图片或者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. TYPE=MyISAM 与 ENGINE=MyISAM 的区别(摘要版)

    TYPE=MyISAM 和 ENGINE=MyISAM 都是设置数据库存储引擎的语句 (老版本的MySQL使用TYPE而不是ENGINE(例如,TYPE = MYISAM). MySQL 5.1为向下 ...

  2. com口操作excel

    _Application app;       //Excel应用程序接口 Workbooks books;        //工作薄集合 _Workbook book;     //工作薄 Work ...

  3. 在线任意进制转换工具 - aTool在线工具

    http://www.atool.org/hexconvert.php ss = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ ...

  4. idea拉出Output窗口和还原窗口

    拉出:按住标题可以拖出 效果: 还原:点击restore layout

  5. Python飞机大战实例有感——pygame如何实现“切歌”以及多曲重奏?

    目录 pygame如何实现"切歌"以及多曲重奏? 一.pygame实现切歌 初始化路径 尝试一 尝试二 尝试三 成功 总结 二.如何在python多线程顺序执行的情况下实现音乐和音 ...

  6. CF147B Smile House

    题目大意:给定一个有向图,其中边有边权.求点数最少的正环的点数. 题解:建立矩阵,处理其二进制上每一位的状态.时间O(n^3*log(n)). 代码: #include<cstdio> # ...

  7. kubernetes 知识点及常用命令

    一.附上一个Deployment文件 apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selec ...

  8. 基于Vue的简单日历组件

    日历组件 由于移动端项目中需要用到日历组件,网上找了下,没看到几个合适的,就尝试着自己写一个.然后发现也不是很复杂,目前只做了最基本的功能,大家也可以拿去做做二次开发. 如何写一个日历组件 基础效果如 ...

  9. flask 开发配置

    flask 开发配置 一:在虚拟机里面安装ubuntu系统.略 二: apt install python3-pip #安装pip, pip3 install --upgrade pip 三: pip ...

  10. 慕课笔记利用css进行布局【一列布局】

    <html> <head> <title>一列布局</title> <style type="text/css"> bo ...