一、说在前面
昨天 | 数据库非一般操作总结 |
今天 | 学习文件下载相关知识 |
二、问题:
1、什么情况下回文件下载?
1)操作实践
2)分析:使用a标签直接指向服务器上的资源,浏览器能解析的文件就直接解析,浏览器不能解析的文件才下载。
3)总结:浏览器不能解析的文件就下载。
2、什么情况下需要在服务器端编写文件下载代码?
1)理论上,浏览器能解析的文件就编写文件下载代码。
2)实际中,只要是需要下载的文件都编写文件下载代码。(浏览器不断更新,维护代码麻烦)
三、文件下载的实现
1、相关知识:
文件下载的实质就是文件拷贝,将文件从服务器端拷贝到浏览器端。所以文件下载需 要IO技术将服务器端的文件使用InputStream读取到,在使用 ServletOutputStream写到response缓冲区中
2、要下载的这个文件的类型-----客户端通过文件的MIME类型去区分类型
1)mime实质Tomcatconf下的web.xml将文件后缀名映射为mime
2)代码获取文件的mime
response.setContentType(this.getServletContext().getMimeType(filename));
3、告示浏览器文件的打开方式是下载:
response.setHeader("Content-Disposition","attachment;filename=文件名称");
4、文件下载的代码
1)前台页面
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h1>1、使用a标签直接指向服务器上的资源</h1> <a href="download/a.flv">a.flv</a><br> <a href="download/a.jpg">a.jpg</a><br> <a href="download/a.mp3">a.mp3</a><br> <a href="download/a.mp4">a.mp4</a><br> <a href="download/a.txt">a.txt</a><br> <a href="download/a.zip">a.zip</a><br> <h1>2、使用服务器端编码的方式实现文件下载</h1> <a href="downloadServlet?filename=a.flv">a.flv</a><br> <a href="downloadServlet?filename=a.jpg">a.jpg</a><br> <a href="downloadServlet?filename=a.mp3">a.mp3</a><br> <a href="downloadServlet?filename=a.mp4">a.mp4</a><br> <a href="downloadServlet?filename=a.txt">a.txt</a><br> <a href="downloadServlet?filename=a.zip">a.zip</a><br> </body> </html>
2)后台servlet
package com.me.servlet; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; 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; @WebServlet("/downloadServlet") public class DownloadServlet extends HttpServlet { private static final long serialVersionUID = 1L; public DownloadServlet() { super(); // TODO Auto-generated constructor stub } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获得要下载的文件的名称 String filename = request.getParameter("filename");// a.flv // 要下载的这个文件的类型-----客户端通过文件的MIME类型去区分类型 response.setContentType(this.getServletContext().getMimeType(filename)); // 告诉客户端该文件不是直接解析 而是以附件形式打开(下载) response.setHeader("Content-Disposition", "attachment;filename=" + filename); // 获取文件的绝对路径 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); } }
3)测试
4、中文乱码问题
但是,如果下载中文文件,页面在下载时会出现中文乱码或不能显示文件名的情况, 原因是不同的浏览器默认对下载文件的编码方式不同,ie是UTF-8编码方式,而火狐 浏览器是Base64编码方式。所里这里需要解决浏览器兼容性问题,解决浏览器兼容 性问题的首要任务是要辨别访问者是ie还是火狐(其他),通过Http请求体中的一 个属性可以辨别
解决乱码方法如下(不要记忆--了解):
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"); }
其中agent就是请求头User-Agent的值