一、文件下载概述

比如图片或者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. C# 支持多线程

    C# 支持多线程并行执行程序 .一个程序由一个单线程开始,该单线程由CLR和操作系统创建而成,并具有多线程创建额外线程的功能. .创建线程的方法 2.1 通过Thread类来创建线程. ThreadS ...

  2. python的unitest的简单使用

    python的unitest的简单使用 unittest提供一个TestLoader类用于自动创建一个测试集并把单个测试放入到测试集中. TestLoader自动运行测试用例以test开头的方法的测试 ...

  3. E. String Multiplication

    E. String Multiplication time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  4. SpringMVC+ajax返回JSON串

    一.引言 本文使用springMVC和ajax做的一个小小的demo,实现将JSON对象返回到页面,没有什么技术含量,纯粹是因为最近项目中引入了springMVC框架. 二.入门例子 ①. 建立工程, ...

  5. sqllite相关总结

    一,sqlite 简介 前面写了一篇博文讲如何在 C# 中使用 ADO 访问各种数据库,在移动开发和嵌入式领域也有一个轻量级的开源关系型数据库-sqlite.它的特点是零配置(无需服务器),单磁盘文件 ...

  6. 秋招复习-C++( 一)

    Linux/Unix编程部分 1.进程间通信方式:信号,信号量,消息队列,共享内存,套接字Socket 2.ipcs: Linux/Unix下的命令,可以用来查看当前系统中所使用的进程间通信方式的各种 ...

  7. linux学习系列博客地址汇总

    2018-09-28 16:03:43 CentOS7 yum命令:这是一个用来管理rpm包进行自动化安装的C/S模式的一个程序. CentOS7(无图形界面)支持中文显示的办法:系统安装好之后,有可 ...

  8. KBE_创建项目和基本常识

    此笔记参考官方文档 第一个项目 资产库:是每一个项目文件夹的名称,使用KBE提供的生成工具生成一个最小资产库,其中包含了很多常用的工具,默认名server_assets: res:放置一些资源(入地图 ...

  9. Spring接收web请求参数的几种方式

    1 查询参数 请求格式:url?参数1=值1&参数2=值2...同时适用于GET和POST方式spring处理查询参数的方法又有几种写法: 方法一:方法参数名即为请求参数名 // 查询参数1 ...

  10. h-ui.admin.pro.iframe头部和标签Tab修改CSS

    原效果:头部高度偏高,tab标签不太好看 ​ 修改后:缩小高度,调整tab标签css样式 ​ 百度网盘链接:https://pan.baidu.com/s/1qknPNAMGL7BFUIsleOF9M ...