servlet方式下载之renponse详解

下载的文件要通过响应传递给浏览器,并且告知浏览器文件的MIME类型,编码,要用下载的方式打开,浏览器不支持下载文件的中文名字,后台要进行编码处理。

下面我们就来详细介绍一下这些方法的使用吧:

第一个例子:通过Response进行数据的输出,下面是一个测试的方法,这个方法只要在service方法中调用即可,传递一个HttpServletResponse对象,就可以进行输出的

[java]  view plain  copy
  1. public void test(HttpServletResponse response) throws Exception{  
  2.     // 使用OutputStream字节流进行数据的输出  
  3.     response.getOutputStream().write("Hello World".getBytes());  
  4. }  

这个例子很简单就是将字符串写到response容器中,然后客户机从容器中拿取数据进行显示即可,但是这里我们需要注意的,当我们在使用response.getOutputStream()这样获取一个OutputStream流的时候,我们在使用完之后,并不需要手动的去关闭,系统会自动关闭它,如果我们手动去关闭这个流的话,还会引发一些问题。


这里我们输出的是"Hello World"英文,使用浏览器去访问的时候是没有乱码问题,下面我们在将代码改写一下,

[java]  view plain  copy
  1. response.getOutputStream.write("中国".getBytes("utf-8"));  
这时候我们使用浏览器去访问数据的时候,当然我们可能会看到"中国",也有可能看到的是乱码,原因很简单,如果浏览器使用的是gb2312码表打开的话,就是乱码,如果是使用utf-8码表打开的话,就是正常的数据。当然我们可以手动的去设置浏览器的打开码表,默认的是gb2312(系统默认码表),那么如果我们使用utf-8将数据写入到Response中,然后浏览器使用的是默认的码表去拿取数据进行显示,那肯定是乱码了,那么我们该怎么办呢?,让用户手动的去修改浏览器的打开码表,那貌似太恶心了,所以这里我们就要介绍一个响应头字段的作用了,Content-type:这个头就是告诉浏览器以什么方式打开数据,并且指定相应的码表,具体代码如下:

[java]  view plain  copy
  1. response.setHeader("Content-type""text/html;charset=utf-8");  
这样,我们就可以告诉浏览器以utf-8码表去显示数据,这样也就不会再有乱码的问题了。

这里我们在扩展一下就是还有一种方式控制浏览器的打开码表,那就是使用<meta>标签来实现:

[java]  view plain  copy
  1. response.getOutputStream().write("<meta http-equiv='content-type' content='text/html;charset=utf-8'>".getBytes());  
这里我们组建了一个<meta>标签,并将这个标签写入到Response容器中,当客户机使用去拿取这段数据的时候,发现有html中的标签<meta>所以会通过一些处理会把上面的字符串当做是是html代码来显示。这里使用了<meat>标签来解决乱码问题的。


上面使用的是字节流的方式来给客户机发送数据的,有时候我们可能会使用字符流来显示数据,因为字符流在特定场合下回比字节流更方便的输出,其实这里使用response.getWriter()来获取一个PrintWriter字符流对象,然后我们可以使用PrintWriter对象的write方法直接写字符串数据,但是这里也是需要来解决乱码的问题,而且这里的需要解决的问题比上面的字节流更麻烦。下面来看一下吧:

[java]  view plain  copy
  1. response.getWriter.write("中国");  
通过上面的方法进行输出,显示的是乱码,首先servlet将"中国"字符串写入到Response容器中,但是这里需要注意的一个问题就是,将"中国"写入到Response中,那么Response容器中是怎么存储"中国"字符串的,因为Response这些技术都是老外发明的,所以他们肯定是使用iso8859-1编码来进行存储字节数据的,所以这里就会有一个大问题,因为我们知道iso8859-1使用的是单个字节表示一个字符的,而gb2312使用的是两个字节,utf-8使用的是三个字节,所以Response将使用iso8859-1码表进行编码,那么存储的是两个乱码字节,所以,当客户机从Response容器中去拿取数据的时候显示的肯定是乱码,那么当我们使用

[java]  view plain  copy
  1. response.setHeader("Content-type","text/html;charset=utf-8")  
来设置浏览器的打开数据的码表,但是我们会发现还是显示两个??,这个也是很简单的,因为我们在编写JavaSE中,也会知道这个问题就是将utf-8这种多字节的码表转到低字节码表iso8859-1,当我这时候在将结果转成utf-8的数据,这时候是不可能在转回原始数据的。所以说我们应该去修改Response容器的码表,将其码表改成utf-8,这时候就可以"中国"写入到Response容器中,而且会以utf-8的码表进行存储的,当客户机在用utf-8码表打开的时候就不会有问题了,

上面我们使用字节流来进行书写数据的时候,是没有问题的,因为是将"中国"的字节数据直接写到Response容器中的,所以不会涉及到Response容器编码的问题。


所以说当我们在使用字符流写入数据的时候,我们一定要记得修改Response容器的编码,不然会出现乱码的

[java]  view plain  copy
  1. response.setCharacterEncoding("utf-8");  
  2. response.setHeader("content-type""text/html;charset=utf-8");  
所以要用这两行代码的,同时response对象中还有一个方法:setContentType,这个方法可以直接设置Content-type字段的值

[java]  view plain  copy
  1. response.setContentType("text/html;charset=utf-8");  
其实这一行代码就相当于上面的两行代码的效果,因为在setContentType方法中已经调用了setCharacterEncoding方法设置了Response容器的编码了。


下面我们在来看一下怎么通过响应头实现下载的,这里我们只是来解决一下下载的文件名是中文的情况:

下面图片就是我们没有去解决文件名是中文的问题。浏览器会过滤中文,并且浏览器会认为其是html类型的数据


下面我们使用URLEncoder.encode(filename,"utf-8");来将中文名进行编码

[java]  view plain  copy
  1. //实现下载  
  2. public void test3(HttpServletResponse response) throws Exception{  
  3.     /** 
  4.     * 这时候就需要通过url进行编码 
  5.     */  
  6.     ServletContext context = this.getServletContext();  
  7.     //通过context方式直接获取文件的路径  
  8.     String path = context.getRealPath("/download/美女.jpeg");  
  9.     //获取文件名  
  10.     String filename = path.substring(path.lastIndexOf("\\")+1);  
  11.     //将文件名进行URL编码  
  12.     filename = URLEncoder.encode(filename,"utf-8");  
  13.     //告诉浏览器用下载的方式打开图片  
  14.     response.setHeader("content-disposition""attachment;filename="+filename);  
  15.     //将图片使用字节流的形式写给客户机  
  16.     InputStream is = this.getServletContext().getResourceAsStream("/download/美女.jpeg");  
  17.     OutputStream out = response.getOutputStream();  
  18.     byte[] buffer = new byte[1024];  
  19.     int len = 0;  
  20.     while((len=is.read(buffer))!=-1){  
  21.         out.write(buffer, 0, len);  
  22.     }  
  23.           
  24. }  
处理之后的效果:


这次就可以正常显示文件名了,而且类型也是jpeg的类型


下面在来看一个例子,就是使用response.getOutputStream流做一个验证码图片的实现案例:

原理:首先我们使用BufferedImage对象获取一个特定高和宽的缓存图片,然后我们将对这个图片对象进行一些修饰加工

setBorder()来设置图片的边框

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值