IT兄弟连 JavaWeb教程 文件下载技术
● 列出提供下载的文件资源
我们要将Web应用系统中的文件资源提供给用户进行下载,首先我们要有一个页面列出上传文件目录下的所有文件,当用户点击文件下载超链接时就进行下载操作,编写一个ListFileServlet,用于列出Web应用系统中所有下载文件。
ListFileServlet的代码如下:
package com.xdl.servlet;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ListFileServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 获取上传文件的目录
String uploadFilePath = this.getServletContext().
getRealPath("/WEB-INF/ upload");
// 存储要下载的文件名
Map<String, String> fileNameMap = new HashMap<String, String>();
// 递归遍历filepath目录下的所有文件和目录,将文件的文件名存储到map集合中
listfile(new File(uploadFilePath), fileNameMap);
// File既可以代表一个文件也可以代表一个目录
// 将Map集合发送到listfile.jsp页面进行显示
request.setAttribute("fileNameMap", fileNameMap);
request.getRequestDispatcher("/listfile.jsp").
forward(request, response);
}
public void listfile(File file, Map<String, String> map) {
// 如果file代表的不是一个文件,而是一个目录
if (!file.isFile()) {
// 列出该目录下的所有文件和目录
File files[] = file.listFiles();
// 遍历files[]数组
for (File f : files) {
// 递归
listfile(f, map);
}
} else {
/**
* 处理文件名,上传后的文件是以uuid_文件名的形式去重新命名的
*/
String realName = file.getName().substring(
file.getName().indexOf ("_") + 1);
// file.getName()得到的是文件的原始名称,这个名称是唯一的,
// 因此可以作为key,realName是处理过后的名称,有可能会重复
map.put(file.getName(), realName);
}
}
}
这里介绍一下ListFileServlet中listfile方法,listfile方法是用来列出目录下的所有文件的,listfile方法内部用到了递归,在实际开发当中,我们肯定会在数据库创建一张表,里面会存储上传的文件名以及文件的具体存放目录,我们通过查询表就可以知道文件的具体存放目录,是不需要用到递归操作的,这个例子是因为没有使用数据库存储上传的文件名和文件的具体存放位置,而上传文件的存放位置又使用了散列算法打散存放,所以需要用到递归,在递归时,将获取到的文件名存放到从外面传递到listfile方法里面的Map集合当中,这样就可以保证所有的文件都存放在同一个Map集合当中。
在web.xml文件中配置ListFileServlet。
<servlet>
<servlet-name>ListFileServlet</servlet-name>
<servlet-class>com.xdl.servlet.ListFileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ListFileServlet</servlet-name>
<url-pattern>/list</url-pattern>
</servlet-mapping>
● 展示下载文件的listfile.jsp页面,代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>兄弟连IT教育</title>
</head>
<body>
<c:forEach var="me" items="${fileNameMap}">
<c:url value="/download" var="downurl">
<c:param name="filename" value="${me.key}"></c:param>
</c:url>
${me.value}<a href="${downurl}">下载</a>
<br />
</c:forEach>
</body>
</html>
访问ListFileServlet,就可以在listfile.jsp页面中显示提供给用户下载的文件资源,如图25所示。

图25 listfile.jsp页面
● 实现文件下载
编写一个用于处理文件下载的Servlet,DownloadServlet的代码如下:
package com.xdl.servlet;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 得到要下载的文件名
String fileName = request.getParameter("filename");
// 上传的文件都是保存在/WEB-INF/upload目录下的子目录当中
String fileSaveRootPath =
this.getServletContext().getRealPath ("/WEB-INF/upload");
// 通过文件名找出文件的所在目录
String path = findFileSavePathByFileName(fileName, fileSaveRootPath);
// 得到要下载的文件
File file = new File(path + "\\" + fileName);
// 如果文件不存在
if (!file.exists()) {
request.setAttribute("message", "您要下载的资源已被删除!!");
request.getRequestDispatcher("/message.jsp").
forward(request, response);
return;
}
// 处理文件名
String realname = fileName.substring(fileName.indexOf("_") + 1);
// 设置响应头,控制浏览器下载该文件
response.setHeader("content-disposition",
"attachment;filename=" + URLEncoder.
encode(realname, "UTF-8"));
// 读取要下载的文件,保存到文件输入流
FileInputStream in = new FileInputStream(path + "\\" + fileName);
// 创建输出流
OutputStream out = response.getOutputStream();
// 创建缓冲区
byte buffer[] = new byte[1024];
int len = 0;
// 循环将输入流中的内容读取到缓冲区当中
while ((len = in.read(buffer)) > 0) {
// 输出缓冲区的内容到浏览器,实现文件下载
out.write(buffer, 0, len);
}
// 关闭文件输入流
in.close();
// 关闭输出流
out.close();
}
public String findFileSavePathByFileName
(String filename, String saveRootPath) {
int hashcode = filename.hashCode();
int dir1 = hashcode & 0xf;
int dir2 = (hashcode & 0xf0) >> 4;
String dir = saveRootPath + "\\" + dir1 + "\\" + dir2;
File file = new File(dir);
if (!file.exists()) {
// 创建目录
file.mkdirs();
}
return dir;
}
}
● 在web.xml文件中配置DownloadServlet。
<servlet>
<servlet-name>DownloadServlet</servlet-name>
<servlet-class>com.xdl.servlet.DownloadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DownloadServlet</servlet-name>
<url-pattern>/download</url-pattern>
</servlet-mapping>
再次访问ListFileServlet,就可以在listfile.jsp页面中点击下载开始下载资源,如图26所示。

图26 下载文件

图27 下载文件成功
从运行结果可以看到,我们的文件下载功能已经可以正常下载文件了。
IT兄弟连 JavaWeb教程 文件下载技术的更多相关文章
- IT兄弟连 JavaWeb教程 AJAX的技术构成
Ajax并不是新的技术,而是之前技术的整合,其中包括JavaScript.HTML.CSS.DOM.XMLHttpRequest.XML和JSON是构成Ajax技术体系技术基石. JavaScript ...
- IT兄弟连 JavaWeb教程 文件上传技术
在Web应用系统开发中,文件上传和下载功能是非常常用的功能. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参 ...
- IT兄弟连 JavaWeb教程 Servlet会话跟踪 Session技术
Servlet提供了HttpSession接口,该接口提供了一种跨多个页面请求或访问网站时识别用户以及存储有关用户信息的方式. Servlet容器使用这个接口来创建一个HTTP客户端和HTTP服务器之 ...
- IT兄弟连 JavaWeb教程 Servlet会话跟踪 Cookie技术原理
Cookie使用HTTPHeader传递数据.Cookie机制定义了两种报头,Set-Cookie报头和Cookie报头.Set-Cookie报头包含于Web服务器的响应头(ResponseHeade ...
- IT兄弟连 JavaWeb教程 Servlet会话跟踪 Cookie技术简介
Cookie的英文原意是“点心”,它是在客户端访问Web服务器时,服务器在客户端硬盘上存放的信息,好像是服务器送给客户的“点心”.服务器可以根据Cookie来跟踪客户状态,这对于需要区别客户的场合(如 ...
- IT兄弟连 JavaWeb教程 MVC设计模式
MVC是Model-View-Controller的简称,即模型-视图-控制器.MVC是一种设计模式,它强制性地把应用程序的数据展示.数据处理和流程控制分开.MVC把应用程序分成3个核心模块:模型.视 ...
- IT兄弟连 JavaWeb教程 ServletContext对象
ServletContext是Servlet与Servlet容器之间直接通信的接口.Servlet容器在启动一个Web应用时,会为它创建一个ServletContext对象.每个Web应用都有唯一的S ...
- IT兄弟连 JavaWeb教程 jQuery对AJAX的支持经典面试题
1.简述对Ajax的理解 AJAX是Asynchronous JavaScript and Xml异步的JavaScript和Xml.它一种用来改善用户体验的技术其实质是使用XMLHttpReques ...
- IT兄弟连 JavaWeb教程 JSON和JSON字符串
JSON (JavaScript Object Notation)是JavaScript语言中的一种对象类型.JSON的好处是易于阅读和解析.当客户端和服务器端需要交互大量数据时,使用JSON格式传输 ...
随机推荐
- Java for LeetCode 119 Pascal's Triangle II
Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3, Return [1,3 ...
- Google IO 2019 Android 太长不看版
Google I/O 2019, 这里有个playlist是所有Android开发相关的session视频合集: Android & Play at Google I/O 2019 当然啦每个 ...
- ActiveMQ 了解
Active MQ 是JMS的一个具体实现,所以首先要对JMS有所了解. 1. JMS: 定义:Java消息服务(Java Message Service),是Sun是提出来的为J2EE提 ...
- Linux tomcat安装详解
一.tomcat安装 1.下载JDK和Tomcat //通过wget下载 wget http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-8 ...
- 【Java】CookieStore 类使用示例
CookieStore 是 Java API 中用来处理 HTTP 客户端的 Cookie 存储策略的类.psd素材 1. [代码]WebClient.java 01import java. ...
- TP框架入门基础
ThinkPHP目录: ThinkPHP主目录文件夹: Conf文件夹: Library文件夹: Library=>Think文件夹:
- 无言以队Alpha阶段项目复审
小组的名字和链接 优点 缺点,bug报告 (至少140字) 最终名次 (无并列) 甜美女孩 http://www.cnblogs.com/serendipity-zeng/p/9937832.html ...
- listen 71
Creepy People Leave You Cold Jack Nicholson, playing the crazed caretaker in The Shining, makes me r ...
- next enum in swift
enum Iter: Int{ case s1=0, s2, s3, s4 mutating func next(){ if self == .s4 { self = .s1 return } sel ...
- redis cluster 实践总结
最近项目接触到了redis cluster,现在趁着使用做一下总结,记录一下遇到过的问题,简单的概述一下常用到的命令和功能. 本篇文章主要是以运维的角度去讲述如何去更好的规划redis clust ...