Servlet学习笔记(八)—— 文件下载

一、文件下载概述

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

时间: 2024-12-17 01:22:26

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

Servlet学习笔记(八)—— 自定义过滤器的编写改进:自定义实现FilterChain

笔记六中实现了三种过滤器:字符编码过滤.登录权限过滤.敏感词过滤,但是有个缺陷就是,限定了过滤顺序,而不能实现先进行request过滤,最后response过滤,并且中间几项过滤的顺序不能动态改变.所以这里做个改进,实现一个过滤顺序的FilterChain. 多个Filter的执行顺序在这篇博文中得到很仔细的讲解,总结一点,多个过滤器的执行顺序是根据web.xml中不同<filter-mapping>的顺序来先后执行的,比如: <?xml version="1.0"

JavaWeb 后端 &lt;二&gt; 之 Servlet 学习笔记

JavaWeb 后端 <二> 之 Servlet 学习笔记 一.Servlet概述 1.什么是Servlet Servlet是一个运行在服务器端的Java小程序,通过HTTP协议用于接收来自客户端请求,并发出响应. 2.Servlet中的方法 public void service(ServletRequest req,ServletResponse res) throws ServletException,java.io.IOException ServletRequest req:代表着请

laravel3学习笔记(八)

原作者博客:ieqi.net ==================================================================================================== Web开发框最大的存在意义无疑是为开发者提供便利,这种被提供的便利不仅表现在对于整个应用接口上的梳理.组织和解耦,也表现在更多细微方便,比如各种工具的提供.Laravel3为开发者提供了各种有关web开发的工具,让开发者在开发应用时只需要关注于自身的业务,而不必在拘泥

测试servlet学习笔记

操作方法: 1.新建工程: File-->new-->Java Project-->TestServlet(工程名称)-->Finish. 2.加载servlet-api.jar类包: TestServlet(右键)-->Build Path-->Configure Build Path-->Library -->Add External JAR Selection-->(浏览在tomcat的lib目录下找到servlet-api.jar选中后点击打开

angular学习笔记(八)

本篇介绍angular控制视图的显示和隐藏: 通过给元素添加ng-show属性或者ng-hide属性来控制视图的显示或隐藏: ng-show: 绑定的数据值为true时,显示元素,值为false时,隐藏元素 ng-hide: 绑定的数据值为true时,隐藏元素,值为false时,显示元素 (其实只要用到其中一个就可以了) 下面来看个简单的例子,点击按钮可以显示/隐藏元素: <!DOCTYPE html> <html ng-app> <head> <title>

SERVLET 学习笔记

SERVLET 学习笔记 一.Servlet基本定义 Servlet是服务器端上面运行的一段小的java程序,一个servlet就是一个简答的java类.通常servlet都是通过请求和返回的模式来被访问的,客户端通过resuest请求,servlet则通过response来返回需要的内容. 二.Tomcat容器等级 Tomcat容器等级分为四个等级,由内向外分别是:context容器àSERVLET容器àHOST(主机)容器àENGINE(引擎)容器.其中,CONTEXT容器,一个CONTEX

Linux System Programming 学习笔记(八) 文件和目录管理

1. 文件和元数据 每个文件都是通过inode引用,每个inode索引节点都具有文件系统中唯一的inode number 一个inode索引节点是存储在Linux文件系统的磁盘介质上的物理对象,也是LInux内核通过数据结构表示的实体 inode存储相关联文件的元数据 ls -i 命令获取文件的inode number /* obtaining the metadata of a file */ #include <sys/types.h> #include <sys/stat.h>

马哥学习笔记八——LAMP编译安装之PHP及xcache

1.解决依赖关系: 请配置好yum源(可以是本地系统光盘)后执行如下命令: # yum -y groupinstall "X Software Development" 如果想让编译的php支持mcrypt扩展,此处还需要下载如下两个rpm包并安装之: libmcrypt-2.5.7-5.el5.i386.rpm libmcrypt-devel-2.5.7-5.el5.i386.rpm 2.编译安装php-5.4.13 首先下载源码包至本地目录. # tar xf php-5.4.13

Lua学习笔记(八):数据结构

table是Lua中唯一的数据结构,其他语言所提供的数据结构,如:arrays.records.lists.queues.sets等,Lua都是通过table来实现,并且在Lua中table很好的实现了这些数据结构. 1.数组 在Lua中通过整数下标访问table中元素,既是数组,并且数组大小不固定,可动态增长.通常我们初始化数组时,就间接地定义了数组的大小,例如: 1 a = {} -- new array 2 for i=1, 1000 do 3 a[i] = 0 4 end 5 6 --数

初探swift语言的学习笔记八(保留了许多OC的实现)

尽管swift作为一门新语言,但还保留了许多OC的机制,使得swift和OC更好的融合在一起.如果没有OC基础的先GOOGLE一下. 如:KVO,DELEGATE,NOTIFICATION. 详见DEMO. import Foundation @objc // 需要打开objc标识,否则@optional编译出错 protocol kvoDemoDelegate { func willDoSomething() @optional func didDoSomething() //可选实现, }