文件下载需求:

1. 页面显示超链接
2. 点击超链接后弹出下载提示框
3. 完成图片文件下载

分析过程:

1. 超链接指向的资源如果能够被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载提示框。不满足需求
2. 任何资源都必须弹出下载提示框
3. 使用响应头设置资源的打开方式:
content-disposition:attachment;filename=xxx

步骤:

1. 定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename
2. 定义Servlet
1. 获取文件名称
2. 使用字节输入流加载文件进内存
3. 指定response的响应头: content-disposition:attachment;filename=xxx
4. 将数据写出到response输出流

  

代码实现:

  下载页面:

 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件下载</title>
</head>
<body> <a href="/day13/img/狐狸.jpg">图片1</a> <a href="/day13/img/2.jpg">图片2</a> <a href="/day13/img/1.avi">视频</a>
<hr> <a href="/day13/downloadservlet?filename=狐狸.jpg">图片1</a> <a href="/day13/downloadservlet?filename=2.jpg">图片2</a> <a href="/day13/downloadservlet?filename=1.avi">视频</a> </body>
</html>

  DownLoadServlet 类

 import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException; @WebServlet("/downloadservlet")
public class downloadservlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1获取请求参数,文件名称
String filename = request.getParameter("filename"); //2使用字节输入流加载文件进内存
// 2.1 找文件服务器路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/img/" + filename); //2.2 使用字节流关联
FileInputStream fis = new FileInputStream(realPath); //3 设置 response 的响应头
// 3.1 设置响应头类型:content-type
String mimeType = servletContext.getMimeType(filename);
response.setHeader("content-type",mimeType);
// 3.2 设置响应头打开方式:content-disposition response.setHeader("content-disposition","attachment;filename="+filename); // 4. 将输入流的数据写出到输出流中
ServletOutputStream sos = response.getOutputStream(); byte[] buff = new byte[1024*8];
int len = 0; while((len = fis.read(buff)) != -1) {
sos.write(buff,0,buff.length);
} // 关闭流对象
fis.close();
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}

  上面的案例中发现,当下载的文件名字是中文的时候,下载的时候会出现乱码。

文件名中文乱码问题

  解决思路:

    (1)获取客户端使用的浏览器版本信息

    (2)根据不同的版本信息,设置 filename 的编码方式不同

  编码工具类:

  使用 Base64 编码,需要导入 commons-codec-1.13.jar 包。

 package cn.itcast.download;

 import org.apache.commons.codec.binary.Base64;   

 import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; public class DownLoadUtils { public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
Base64 base64Encoder = new Base64();
// 火狐浏览器
//BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}

  DownLoadServlet 类(改进):

 package cn.itcast.download;

 import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException; @WebServlet("/downloadservlet")
public class downloadservlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1获取请求参数,文件名称
String filename = request.getParameter("filename"); //2使用字节输入流加载文件进内存
// 2.1 找文件服务器路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/img/" + filename); //2.2 使用字节流关联
FileInputStream fis = new FileInputStream(realPath); //3 设置 response 的响应头
// 3.1 设置响应头类型:content-type
String mimeType = servletContext.getMimeType(filename);
response.setHeader("content-type",mimeType);
// 3.2 设置响应头打开方式:content-disposition // 3.3 解决中文文件名问题
// 1 获取 user-agent 请求头
String agent = request.getHeader("user-agent");
// 2 使用工具类方法编码文件即可
filename = DownLoadUtils.getFileName(agent, filename); response.setHeader("content-disposition","attachment;filename="+filename); // 4. 将输入流的数据写出到输出流中
ServletOutputStream sos = response.getOutputStream(); byte[] buff = new byte[1024*8];
int len = 0; while((len = fis.read(buff)) != -1) {
sos.write(buff,0,buff.length);
} // 关闭流对象
fis.close();
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}

Java 之 Response 文件下载案例的更多相关文章

  1. request和response文件下载案例

    一.需求分析 * 文件下载需求: 1. 页面显示超链接 2. 点击超链接后弹出下载提示框 3. 完成图片文件下载 * 分析: 1. 超链接指向的资源如果能够被浏览器解析,则在浏览器中展示,如果不能解析 ...

  2. Java中都通用文件下载(ContentType、文件头、response、out四步骤)

    Java中都通用文件下载(ContentType.文件头.response.out四步骤) 新浪微博:IT国子监(记得关注噢) http://weibo.com/itguozijian   我们就直接 ...

  3. Java虚拟机类加载机制——案例分析

    转载: Java虚拟机类加载机制--案例分析   在<Java虚拟机类加载机制>一文中详细阐述了类加载的过程,并举了几个例子进行了简要分析,在文章的最后留了一个悬念给各位,这里来揭开这个悬 ...

  4. Java学生管理系统项目案例

    这是一个不错的Java学生管理系统项目案例,希望能够帮到大家的学习吧. 分代码如下 package com.student.util; import java.sql.Connection; impo ...

  5. Java多态面试题案例几解题思路

    ---恢复内容开始--- Java多态面试题案例几解题思路 这道题是来自别人,先开始看到题很懵,后来有自己的思路: class A { public String show(D obj){ retur ...

  6. java基础-多线程应用案例展示

    java基础-多线程应用案例展示 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.两只熊,100只蜜蜂,蜜蜂每次生产的蜂蜜量是1,罐子的容量是30,熊在罐子的蜂蜜量达到20的时候 ...

  7. Java基础-数据类型应用案例展示

    Java基础-数据类型应用案例展示 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.把long数据转换成字节数组,把字节数组数据转换成long. /* @author :yinz ...

  8. JAVA WEB项目开发案例精粹

    http://www.blogjava.net/zongbao/archive/2012/07/24/383884.htmlJAVA WEB项目开发案例精粹.pdf main Alt + / => ...

  9. zabbix java gateway配置实战案例

    zabbix java gateway配置实战案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.部署tomcat服务 博主推荐阅读: CentOS: https://www. ...

随机推荐

  1. Token 安全登陆防止窃取

    HTTP 协议是无状态的 在web中使用cookie+session的技术来保持用户登陆的状态 移动端使用token来保持用户登陆状态由于token在网络中传输,很容易被 中间人获取,进而模拟用户进行 ...

  2. flutter 高德地图选择位置信息返回

    添加依赖:(注意,作者一直更新维护,请以最新的版本添加) amap_map_fluttify: ^ amap_search_fluttify: ^ 代码实现: import 'package:amap ...

  3. SpringBoot项目从Git拉取代码并完成编译打包启动的sh自动脚本

    操作步骤: 1.进入/home/servers/codes/xxxx-dev/目录,从git上将项目clone下来: 2.确保/usr/local/xxx/xxxx-dev目录存在: 3.确保sh脚本 ...

  4. openvswitch2.11.0修改源码后重新编译(2)

    一:前提 已经正常安装了SDN环境(mininet和openswitch2.11.0和Ryu) 使用前面教程安装环境SDN实验---使用git安装Mininet (一)测试ovs是否正常使用 1.ry ...

  5. linux驱动开发学习一:创建一个字符设备

    首先是内核初始化函数.代码如下.主要是三个步骤.1 生成设备号. 2 注册设备号.3 创建设备. #include <linux/module.h> #include <linux/ ...

  6. Quartz学习笔记:集群部署&高可用

    Quartz学习笔记:集群部署&高可用 集群部署 一个Quartz集群中的每个节点是一个独立的Quartz应用,它又管理着其他的节点.这就意味着你必须对每个节点分别启动或停止.Quartz集群 ...

  7. Content-type"是"application/json的作用

    request中发送json数据用post方式发送Content-type用application/json;charset=utf-8方式发送的话,直接用springMVC的@RequestBody ...

  8. NFS挂载参数

    mount -t nfs -o rw,bg,hard,nointr,rsize=32768,wsize=32768,tcp,actimeo=0,vers=3,timeo=6 192.168.12.50 ...

  9. windows和linux环境下java调用C++代码-JNI技术

    最近部门做安卓移动开发的需要调C++的代码,困难重重,最后任务交给了我,查找相关资料,没有一个教程能把不同环境(windows,linux)下怎么调用说明白的,自己在实现的过程中踩了几个坑,在这里总结 ...

  10. Django框架之第三篇(路由层)--有名/无名分组、反向解析、路由分发、名称空间、伪静态

    一.Django请求生命周期 二.路由层  urls.py url()方法 第一个参数其实就是一个正则表达式,一旦前面的正则匹配到了内容,就不会再往下继续匹配,而是直接执行对应的视图函数. djang ...