创建时间:6.19 & 6.24

1.案例-完成文件下载

1)  什么情况下会文件下载?

浏览器不能解析的文件就下载

*使用a标签直接指向服务器上的资源

2)什么情况下需要在服务端编写文件下载的代码?

理论上,浏览器可以解析的代码需要编写文件下载代码

实际开发中,只要是下载的文件都编写文件下载代码

文件下载的实质就是文件拷贝,将文件从服务器端拷贝到浏览器端。所以文件下载需要IO技术将服务器端的文件使用InputStream读取到,在使用      ServletOutputStream写到response缓冲区中

代码如下:

上述代码可以将图片从服务器端传输到浏览器,但浏览器直接解析图片显示在页面上,而不是提供下载,我们需要设置两个响应头,告知浏览器文件的类型和文件的打开方式。

1)告知浏览器文件的类型:response.setContentType(文件的MIME类型);

2)告示浏览器文件的打开方式是下载:

response.setHeader("Content-Disposition","attachment;filename=文件名称");

代码如下:

*客户端不是根据文件扩展名来区分文件的类型,而是通过文件的MIME类型(在tomcat的web.xml中对extension进行MIME的映射)

但是,如果下载中文文件,页面在下载时会出现中文乱码或不能显示文件名的情况,  原因是不同的浏览器默认对下载文件的编码方式不同,ie是UTF-8编码方式,而火狐浏览器是Base64编码方式。所里这里需要解决浏览器兼容性问题,解决浏览器兼容   性问题的首要任务是要辨别访问者是ie还是火狐(其他),通过Http请求体中的一个属性可以辨别

解决乱码方法如下(不要记忆--了解):

其中agent就是请求头User-Agent的值

 if (agent.contains("MSIE")) {

             // IE浏览器

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

             filename = filename.replace("+", " ");

 } else if (agent.contains("Firefox")) {

             // 火狐浏览器

 BASE64Encoder base64Encoder = new BASE64Encoder();

             filename = "=?utf-8?B?"

                       + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";

 } else {

             // 其它浏览器

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

 }

完整代码:见WEB14代码DownloadServlet2.java

 package com.itheima.content;

 import java.io.FileInputStream;

 import java.io.IOException;

 import java.io.InputStream;

 import java.net.URLEncoder;

 import javax.servlet.ServletException;

 import javax.servlet.ServletOutputStream;

 import javax.servlet.http.HttpServlet;

 import javax.servlet.http.HttpServletRequest;

 import javax.servlet.http.HttpServletResponse;

 import sun.misc.BASE64Encoder;

 public class DownLoadServlet2 extends HttpServlet {

       protected void doGet(HttpServletRequest request, HttpServletResponse response)

                   throws ServletException, IOException {

             //*******文件名称是中文的下载*******

             //获得要下载的文件的名称

             String filename = request.getParameter("filename");//????.jpg

             //解决获得中文参数的乱码----下节课讲

             filename = new String(filename.getBytes("ISO8859-1"),"UTF-8");//美女.jpg

             //获得请求头中的User-Agent

             String agent = request.getHeader("User-Agent");

             //根据不同浏览器进行不同的编码

             String filenameEncoder = "";

             if (agent.contains("MSIE")) {

                   // IE浏览器

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

                   filenameEncoder = filenameEncoder.replace("+", " ");

             } else if (agent.contains("Firefox")) {

                   // 火狐浏览器

                   BASE64Encoder base64Encoder = new BASE64Encoder();

                   filenameEncoder = "=?utf-8?B?"

                              + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";

             } else {

                   // 其它浏览器

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

             }

             //要下载的这个文件的类型-----客户端通过文件的MIME类型去区分类型

             response.setContentType(this.getServletContext().getMimeType(filename));

             //告诉客户端该文件不是直接解析 而是以附件形式打开(下载)----filename="+filename 客户端默认对名字进行解码

             response.setHeader("Content-Disposition", "attachment;filename="+filenameEncoder);

             //获取文件的绝对路径

             String path = this.getServletContext().getRealPath("download/"+filename);

             //获得该文件的输入流

             InputStream in = new FileInputStream(path);

             //获得输出流---通过response获得的输出流 用于向客户端写内容

             ServletOutputStream out = response.getOutputStream();

             //文件拷贝的模板代码

             int len = 0;

             byte[] buffer = new byte[1024];

             while((len=in.read(buffer))>0){

                   out.write(buffer, 0, len);

             }

             in.close();

             //out.close();

       }

       protected void doPost(HttpServletRequest request, HttpServletResponse response)

                   throws ServletException, IOException {

             doGet(request, response);

       }

 }

response细节点:

1)response获得的流不需要手动关闭,web容器(tomcat)会帮助我们关闭

2)getWriter和getOutputStream不能同时调用

验证码案例:不用掌握生成验证码,只要掌握html页面里怎么改

[转]【HttpServlet】HttpServletResponse接口 案例:完成文件下载的更多相关文章

  1. HttpServletRequest 接口、HttpServletResponse 接口、请求转发与重定向

    上篇文章我们讲了servlet的基本原理,这章将讲一下剩余的部分. HttpServletRequest 接口 该接口是 ServletRequest 接口的子接口,封装了 HTTP 请求的相关信息, ...

  2. Servlet(6)—HttpServletRequest接口和HttpServletResponse接口

    HttpServletRequest接口和HttpServletResponse接口是继承ServletRequest和ServletResponse接口,是他们的子接口,但是我们在程序中进程看到Se ...

  3. HttpServletRequest HttpServletResponse接口详解

    HttpServletRequest接口最常用的方法就是获得请求中的参数,这些参数一般是客户端表单中的数据.同时,HttpServletRequest接口可以获取由客户端传送的名称,也可以获取产生请求 ...

  4. Yarn的Tool接口案例

    目录 Yarn的Tool接口案例 Tool接口环境准备 1 新建Maven项目YarnDemo 编写代码 打包jar上传到集群 Yarn的Tool接口案例 Tool接口环境准备 之前写wordcoun ...

  5. HttpServletResponse接口详解

    在 Servlet API 中,定义了一个 HttpServletResponse 接口,它继承自 ServletResponse 接口.HttpServletResponse 对象专门用来封装 HT ...

  6. HttpServletResponse接口

    public interface HttpServletResponse extends ServletResponse 描述一个返回到客户端的HTTP回应.这个接口允许Servlet程序员利用HTT ...

  7. Servlet--HttpServletRequest接口,HttpServletResponse接口

    HttpServletRequest接口 定义 public interface HttpServletRequest extends ServletRequest; 用来处理一个对 Servlet ...

  8. JavaWeb案例: 文件下载 基于tomcat8 默认编码为UTF-8

    package cn.itcast.download; import javax.servlet.ServletException; import javax.servlet.ServletOutpu ...

  9. [转]【response】HttpServletResponse接口

    创建时间:6.19 & 6.24 1.HttpServletResponse概述 我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参 ...

随机推荐

  1. 从网络服务生成Apex类

    使用WSDL2Apex从网络服务生成Apex类 如果某个网络服务被定义在WSDL文件中,而Salesforce必须使用SOAP和网络服务进行通信,则这种情况在某些时候会为开发者带来很多麻烦.为了简化S ...

  2. [LeetCode] 743. Network Delay Time 网络延迟时间

    There are N network nodes, labelled 1 to N. Given times, a list of travel times as directededges tim ...

  3. [LeetCode] 545. Boundary of Binary Tree 二叉树的边界

    Given a binary tree, return the values of its boundary in anti-clockwise direction starting from roo ...

  4. 这篇文章主要讲解C#中的泛型,泛型在C#中有很重要的地位,尤其是在搭建项目框架的时候。

    一.什么是泛型 泛型是C#2.0推出的新语法,不是语法糖,而是2.0由框架升级提供的功能. 我们在编程程序时,经常会遇到功能非常相似的模块,只是它们处理的数据不一样.但我们没有办法,只能分别写多个方法 ...

  5. 阅读java编程思想之一切都是对象

    温故而知新--- 1. 用句柄操作对象 现实生活中,我们可以把遥控器当作句柄,电视机当作对象.当我们拿到句柄(遥控器)的时候,我们是可以控制对象的(电视机).比如说调节音量大小,色彩等.那么在程序里, ...

  6. Ubuntu安装完搜狗后,更改ctrl+shift切换输入法

    1.打开搜狗设置 2.更改Scroll between Input Method即可,我设置成了 ALT_SUPER(Win键)

  7. c++ 使用 vcpkg

    1. 打开下载地址:https://github.com/Microsoft/vcpkg 2. 直接下载到本地某个盘 3. 配置环境变量: 4. 打开下载到本地的vcpkg有可能叫vcpkg-mast ...

  8. 框架之jQuery妙用

    1.jQuery介绍 jQuery是一个轻量级的.兼容多浏览器的JavaScript库. jQuery使用户能够更方便地处理HTML Document.Events.实现动画效果.方便地进行Ajax交 ...

  9. 第三次实验报告:使用Packet Tracer分析TCP连接建立过程

    目录 1 实验目的 2 实验内容 3. 实验报告 3.1 建立网络拓扑结构 3.2 配置参数 3.3 抓包,分析TCP连接建立过程 4. 拓展 (不作要求,但属于加分项) 1 实验目的 使用路由器连接 ...

  10. LeetCode 28:实现strStr() Implement strStr()

    爱写bug(ID:icodebugs) 作者:爱写bug 实现 strStr() 函数. 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needl ...