Servlet 实现文件下载

在生活或者工作中,总是避免不了下载文件,下载的东西有各种类型,譬如图片,视频,文本,文档,音乐等等,这些东西有大有小,大的有几G到几十G,小的或许只有几K。这些东西究竟是如何从服务器下载到我们本地的呢?现在就利用 Servlet 来实现一个的文件下载功能。

前提

要想完成这个案例,需要如下技术:

Java 基础

HTML 基础

会使用 Tomcat 服务器

会使用 Servlet 进行开发

了解 HTTP 协议

会使用 Response 设置响应头、响应消息行

准备工作

所谓工欲善其事,必先利其器。要完成这个案例,我们得做好准备工作。

首先,打开 Eclipse,新建一个 Dynamic Web Project。

键入项目名,选择运行时环境为 Apache Tomcat v7.0,选择 web 版本为 2.5,然后点击 Finished。

在项目的 WebContent 目录下,新建一个文件夹 download,然后将可以供给用户下载的文件存放在这个文件夹里。

在 WebContent 目录下新建一个 index.html。

代码如下:

Insert title here

准备工作完成!

在 WebContent -> WEB-INF 目录下新建一个 web.xml 文件,这是 web2.5 版本的规范,一个 web.xml 文件可以对 web 项目进行基本的配置。

代码如下:

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">

download

index.html

使用 Tomcat 将次项目发布,并在浏览器中预览。

将服务器启动,然后在浏览器中输入:http://localhost:8080/download。如果出现以下界面,那么恭喜你,准备工作完美完成!

完成案例

超链接下载文件

也许有人会说,下载文件有什么难的,在 index.html 中编写几个 a 标签,将 href 属性设置为供给用户下载的文件的路径不就行了?

那么,我就按照上述所说试验:

首先,在 index.html 中编写3个 a 标签,将 href 属性分别指向了供给用户下载的文件的路径。

下载

图片

文本

文档

然后,在浏览器中打开 index.html。

这样看似乎并没有什么问题,那么来点击超链接试验一下。

结果,有的文件直接在浏览器打开了,而有的文件则是下载了。这究竟是什么原因呢?原来,当浏览器能够解析该文件的 MIME类型,则直接打开该文件;若不能,则下载。

如此,看来使用超链接下载文件是行不通了。

编码下载

从以上分析可以看出,要实现文件下载并不是设置 a 标签那么简单的。那么,究竟该怎样实现文件下载功能呢?此时,就需要使用 Servlet 编码读取要下载的文件,然后写到响应流中以达到用户下载文件的目的。

在这里,我们使用 get 请求方式,将文件名放在 url 中传送给服务器,但在很多情况下使用 post 发送数据给服务器更加合适。通过 get 发送大量数据是不现实的,它有一定的局限性,在这里使用 get 方式只是为了方便。

首先,新建一个 Servlet,并编写 web.xml 设置它的访问路径:

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">

download

index.html

DownloadServlet

club.luckylight.servlet.DownloadServlet

DownloadServlet

/DownloadServlet

然后,需要修改 index.html 页面中 a 标签的 href 属性:

下载

图片

文本

文档

接下来,就可以开始编写 Servlet 了:

首先,从 url 中获取文件名

String filename = request.getParameter("name");

接下来,获取根据文件名获取文件的 MIME类型

String mimeType = getServletContext().getMimeType(filename);

然后,就需要设置文件的 MIME类型

response.setContentType(mimeType);

上条语句的作用就是使客户端浏览器,区分不同种类的数据,并根据不同的 MIME类型 调用浏览器内不同的程序嵌入模块来处理相应的数据。例如浏览器就是通过 MIME类型 来判断文件是 gif 图片,还是 doc 文档的。

光是这些还不行,下面还要告诉浏览器 “我要下载东西”

response.setHeader("content-disposition", "attachment;filename=" + filename);

最后,把文件从服务器拷贝到浏览器,完成下载

// 定义输入流

InputStream is = getServletContext().getResourceAsStream("/download/" + filename);

// 定义输出流

ServletOutputStream os = response.getOutputStream();

// 从文件中读入数据并写到输出字节流中

int len = -1;

byte[] bytes = new byte[1024];

while ((len = is.read(bytes)) != -1) {

os.write(bytes, 0, len);

}

// 关闭资源

os.close();

is.close();

下面,我来测试一下:

如此看来,似乎也并没有什么问题,但是我设置的文件名都是数字,如果我将文件名都设置为中文,那么又会怎样呢?

此时,对于 get 请求,参数追加到地址栏,会使用 utf-8 编码,服务器(Tomcat)接受到请求之后,使用 iso-8859-1 解码,所以会出现乱码,导致找不到资源。

因此,我们在获取文件名时,必须将文件名用 utf-8 解码,然后才能使用。

String filename = new String(request.getParameter("name").getBytes("iso-8859-1"), "utf-8");

经过上述处理后,虽然能够下载了,但又出现了:浏览器无法识别文件名。

此时,我们需要编写一个工具类,以解决这个问题。

新建一个 class,设置类名为 DownloadUtils,编写一个静态方法,作用是根据浏览器的不同把传递过来的文件名编码。

package club.luckylight.util;

import java.io.UnsupportedEncodingException;

import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;

public class DownloadUtils {

public static String getFilename(HttpServletRequest request, String filename) throws UnsupportedEncodingException {

String userAgent = request.getHeader("user-agent");

// 针对以IE或者Edge为内核的浏览器

if (userAgent.contains("MSIE") || userAgent.contains("Trident") || userAgent.contains("Edge")) {

filename = URLEncoder.encode(filename, "UTF-8");

} else {

// 非IE浏览器的处理

filename = new String(filename.getBytes("UTF-8"), "ISO-8859-1");

}

return filename;

}

}

然后,在告诉浏览器 “我要下载东西” 之前,把文件名编码。

String newFilename = DownloadUtils.getFilename(request, filename);

response.setHeader("content-disposition", "attachment;filename=" + newFilename);

根据测试,以上工具类可以解决主流浏览器(IE内核,Edge内核,Chrom,FireFox等)文件下载时文件名乱码问题。

完整代码

DownloadUtils.java

package club.luckylight.util;

import java.io.UnsupportedEncodingException;

import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;

public class DownloadUtils {

public static String getFilename(HttpServletRequest request, String filename) throws UnsupportedEncodingException {

String userAgent = request.getHeader("user-agent");

// 针对以IE或者Edge为内核的浏览器

if (userAgent.contains("MSIE") || userAgent.contains("Trident") || userAgent.contains("Edge")) {

filename = URLEncoder.encode(filename, "UTF-8");

} else {

// 非IE浏览器的处理

filename = new String(filename.getBytes("UTF-8"), "ISO-8859-1");

}

return filename;

}

}

DownloadServlet.java

package club.luckylight.servlet;

import java.io.IOException;

import java.io.InputStream;

import javax.servlet.ServletException;

import javax.servlet.ServletOutputStream;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import club.luckylight.util.DownloadUtils;

public class DownloadServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// 获取文件名,并设置编码

String filename = new String(request.getParameter("name").getBytes("iso-8859-1"), "utf-8");

// 获取文件的mime类型

String mimeType = getServletContext().getMimeType(filename);

// 设置文件的mime类型

response.setContentType(mimeType);

// 文件名编码

String newFilename = DownloadUtils.getFilename(request, filename);

// 设置下载头信息

response.setHeader("content-disposition", "attachment;filename=" + newFilename);

// 对拷流

InputStream is = getServletContext().getResourceAsStream("/download/" + filename);

ServletOutputStream os = response.getOutputStream();

int len = -1;

byte[] bytes = new byte[1024];

while ((len = is.read(bytes)) != -1) {

os.write(bytes, 0, len);

}

// 关闭资源

os.close();

is.close();

}

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

doGet(request, response);

}

}

总结

至此,文件下载案例就完成了。其中有许多小细节并没有处理,如发现有什么错误,请多多指点。

这也是我第一次写一个案例,希望大家喜欢。

java servlet文件下载_Servlet 实现文件下载相关推荐

  1. java servlet 多线程_Servlet的多线程和线程安全

    线程安全 首先说明一下对线程安全的讨论,哪种情况我们可以称作线程安全? 网上对线程安全有很多描述,我比较喜欢<Java并发编程实战>给出的定义,"当多个线程访问某个类时,不管运行 ...

  2. java servlet文件下载_Servlet实现文件下载功能

    本文实例为大家分享了Servlet实现文件下载的具体代码,供大家参考,具体内容如下 把文件目录直接暴露给用户是很不安全的.所以要用Servlet来做,而且这样做,文件的存储方式就更丰富了,可以是从文件 ...

  3. java servlet 作用_servlet的作用,servlet有什么用?

    Servlet我们经常说到,那你们知道servlet的作用是什么吗?下面通过这篇文章一起来了解一下吧. servlet作用 当我们在使用一个交互式 的Web站点的时候,我们所浏览到的所有内容都应该是在 ...

  4. java servlet例子_Servlet学习教程(三)---- 一个简单的Servlet例子

    我们用个最简单的Servlet例子来解说一下Servlet简单配置以及Servlet类实现类的写法. 第一,我们新建一个Dynamic Web Project,起名Servlet 点击NEXT,设置D ...

  5. java servlet 入门_servlet 入门详解

    servlet 入门详解 Servlet是一种服务器端的编程语言,是J2EE中比较关键的组成部分.Servlet本质上也是Java类,编写Servlet需要遵循java的基本语法,但是与一般的Java ...

  6. java servlet验证码_Servlet 实现验证码

    分析 生成图片实现类 ① 定义BufferedImage 对象 ② 获得 Graphics 对象 ③ 通过 Random 产生随机验证码信息 ④ 使用 Graphics 绘制图片 ⑤ 记录验证码信息到 ...

  7. java servlet作用_Servlet的功能是什么

    servlet是很复杂的东西,事实上,servlet就是一个Java接口,interface! 打开idea,ctrl + shift + n,搜索servlet,就可以看到是一个只有5个方法的int ...

  8. java servlet试题_Servlet面试题库 选择题

    2015-11-27 06:30:03 阅读( 247 ) 1.有两个Servlet:servlet1和servlet2,servlet1把HttpServletRequest和HttpServlet ...

  9. java servlet 配置_servlet与javabean配置

    servlet与javabean配置 (一):目录结构 tomcat的目录结构如下: 目录名 简介 bin 存放启动和关闭tomcat脚本 conf 包含不同的配置文件,server.xml(Tomc ...

最新文章

  1. Blender制作3D模型导出到UE5完整学习教程
  2. 20分钟一键自动化部署10台集群规模实战(隆重分享)
  3. zabbix之通过jmx监控tomcat
  4. Java String.split() 特殊字符处理
  5. 深入探讨用位掩码代替分支(3):VC6速度测试
  6. 440. 字典序的第K小数字
  7. php mvc 路由,PHP手写MVC (五)—— 路由
  8. Android Sqite数据库 6
  9. 信息学奥赛一本通 1077:统计满足条件的4位数 | OpenJudge NOI 1.5 26
  10. 堪比整容!学会这些可视化技巧,让你的图表分分钟高级起来
  11. MVC Razor基础
  12. idea 创建项目并同步到git仓库
  13. SQL server如何自定义服务器名称登陆
  14. 数据分析系列 9/32 | Excel进行回归分析,预测真实值
  15. JSON Editor 中文文档
  16. 动态路由id会拼接到地址栏中,如何获取这个id
  17. org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘emp
  18. 如何在linux中关闭一个进程
  19. 讲座:与迷茫为友的成长(贺利坚老师,烟台大学)——完整讲座PPT,精彩与动画媲美
  20. Linux云主机开启IPv6服务

热门文章

  1. 服务器固态硬盘raid没了,HP服务器磁盘阵列坏了怎么办,数据如何恢复?
  2. 统计每天的新老用户,日活,周活,月活
  3. set name utd8_ml utd 8机器学习数据的最新生命
  4. android遥控器适配
  5. Android使用keytool-importkeypair生成一个系统签名,只要打包的时候使用该签名,便可以获得系统所有权限
  6. STVD 新建STM8L151工程
  7. vue 视频播放(使用vue-video-player)
  8. money as debt 笔记
  9. 【更新21.02.03】百分浏览器继续使用Flash Player的临时解决方案!
  10. 扫地机器人自动回冲工作原理