创建时间: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的值
1 if (agent.contains("MSIE")) { 2 3 // IE浏览器 4 5 filename = URLEncoder.encode(filename, "utf-8"); 6 7 filename = filename.replace("+", " "); 8 9 } else if (agent.contains("Firefox")) { 10 11 // 火狐浏览器 12 13 BASE64Encoder base64Encoder = new BASE64Encoder(); 14 15 filename = "=?utf-8?B?" 16 17 + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; 18 19 } else { 20 21 // 其它浏览器 22 23 filename = URLEncoder.encode(filename, "utf-8"); 24 25 }
完整代码:见WEB14代码DownloadServlet2.java
1 package com.itheima.content; 2 3 4 5 import java.io.FileInputStream; 6 7 import java.io.IOException; 8 9 import java.io.InputStream; 10 11 import java.net.URLEncoder; 12 13 14 15 import javax.servlet.ServletException; 16 17 import javax.servlet.ServletOutputStream; 18 19 import javax.servlet.http.HttpServlet; 20 21 import javax.servlet.http.HttpServletRequest; 22 23 import javax.servlet.http.HttpServletResponse; 24 25 26 27 import sun.misc.BASE64Encoder; 28 29 30 31 public class DownLoadServlet2 extends HttpServlet { 32 33 34 35 protected void doGet(HttpServletRequest request, HttpServletResponse response) 36 37 throws ServletException, IOException { 38 39 40 41 //*******文件名称是中文的下载******* 42 43 44 45 46 47 //获得要下载的文件的名称 48 49 String filename = request.getParameter("filename");//????.jpg 50 51 //解决获得中文参数的乱码----下节课讲 52 53 filename = new String(filename.getBytes("ISO8859-1"),"UTF-8");//美女.jpg 54 55 56 57 58 59 //获得请求头中的User-Agent 60 61 String agent = request.getHeader("User-Agent"); 62 63 //根据不同浏览器进行不同的编码 64 65 String filenameEncoder = ""; 66 67 if (agent.contains("MSIE")) { 68 69 // IE浏览器 70 71 filenameEncoder = URLEncoder.encode(filename, "utf-8"); 72 73 filenameEncoder = filenameEncoder.replace("+", " "); 74 75 } else if (agent.contains("Firefox")) { 76 77 // 火狐浏览器 78 79 BASE64Encoder base64Encoder = new BASE64Encoder(); 80 81 filenameEncoder = "=?utf-8?B?" 82 83 + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; 84 85 } else { 86 87 // 其它浏览器 88 89 filenameEncoder = URLEncoder.encode(filename, "utf-8"); 90 91 } 92 93 94 95 96 97 98 99 //要下载的这个文件的类型-----客户端通过文件的MIME类型去区分类型 100 101 response.setContentType(this.getServletContext().getMimeType(filename)); 102 103 //告诉客户端该文件不是直接解析 而是以附件形式打开(下载)----filename="+filename 客户端默认对名字进行解码 104 105 response.setHeader("Content-Disposition", "attachment;filename="+filenameEncoder); 106 107 108 109 //获取文件的绝对路径 110 111 String path = this.getServletContext().getRealPath("download/"+filename); 112 113 //获得该文件的输入流 114 115 InputStream in = new FileInputStream(path); 116 117 //获得输出流---通过response获得的输出流 用于向客户端写内容 118 119 ServletOutputStream out = response.getOutputStream(); 120 121 //文件拷贝的模板代码 122 123 int len = 0; 124 125 byte[] buffer = new byte[1024]; 126 127 while((len=in.read(buffer))>0){ 128 129 out.write(buffer, 0, len); 130 131 } 132 133 134 135 in.close(); 136 137 //out.close(); 138 139 140 141 } 142 143 144 145 protected void doPost(HttpServletRequest request, HttpServletResponse response) 146 147 throws ServletException, IOException { 148 149 doGet(request, response); 150 151 } 152 153 }
response细节点:
1)response获得的流不需要手动关闭,web容器(tomcat)会帮助我们关闭
2)getWriter和getOutputStream不能同时调用
验证码案例:不用掌握生成验证码,只要掌握html页面里怎么改