文件下载详述
文件下载
目录
1、文件下载就是向客户端响应字节数据!
2、下载的要求:两个头一个流!
3、编写文件下载代码
4、下载的细节
----------------------------------------------------------------------------------------------------------------------
1、文件下载就是向客户端响应字节数据!
以前我们响应的都是html的字符数据,直接展示在浏览器上,现在要作为一个文件下载下来,而不是直接展示在浏览器上,
把一个文件变成字节数组,使用response.getOutputStream()来响应给浏览器!!!
2、下载的要求:两个头一个流!
Content-Type:你传递给客户端的文件是什么MIME类型,例如:image/pjpeg
* 通过文件名称调用ServletContext的getMimeType()方法,得到MIME类型!
Content-Disposition:它的默认值为inline,表示在浏览器窗口中打开!attachment;filename=xxx
* 在filename=后面跟随的是显示在下载框中的文件名称!
流:要下载的文件数据!
* 自己new一个输入流即可!
3、编写文件下载代码
描述:被下载的资源必须放到 WEB-INF 安全目录下(只要用户不能通过浏览器直接访问就OK),然后通过Servlet完成下载。在jsp页面中给出超链接,链接到DownloadServlet,并提供要下载的文件名称。然后DownloadServlet获取文件的真实路径,然后把文件写入到response.getOutputStream()流中。
download.jsp
<body> This is my JSP page. <br> <a href="<c:url value='/DownloadServlet?filename=a.avi'/>">a.avi</a><br/> <a href="<c:url value='/DownloadServlet?filename=a.jpg'/>">a.jpg</a><br/> <a href="<c:url value='/DownloadServlet?filename=a.txt'/>">a.txt</a><br/> </body> |
DownloadServlet.java (使用了commons-io-1.4.jar工具包)
@Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); /* * 两个头一个流 * 1. Content-Type * 2. Content-Disposition * 3. 流:下载文件的数据 */ //得到前台传过来的文件名 String filename = request.getParameter("filename"); //该文件的在服务器的路径 String filepath = this.getServletContext().getRealPath("/WEB-INF/uploads/" + filename); File file = new File(filepath); if(!file.exists()) { response.getWriter().print("您要下载的文件不存在!"); return; }else{ //设置2个响应头 //通过文件名称获取MIME类型(根据文件名的后缀) response.setHeader("Content-Type", this.getServletContext().getMimeType(filename)); //该头信息,可以使下载框显示下载的文件名 response.setHeader("Content-Disposition", "attachment;filename=" + filenameEncoding("流光%飞舞.mp3", request));
// 1个流 FileInputStream input = new FileInputStream(file); ServletOutputStream output = response.getOutputStream();// 获取绑定了响应端的流 IOUtils.copy(input, output);//把输入流中的数据写入到输出流中。 input.close(); }
}
// 解决不同浏览器中文乱码问题,用来对下载的文件名称进行编码的! public static String filenameEncoding(String filename, HttpServletRequest request) throws IOException { String agent = request.getHeader("User-Agent"); //获取浏览器 if (agent.contains("Firefox")) { //火狐用的是BASE64Encoder 来编码和解码 filename = "=?utf-8?B?" + new BASE64Encoder().encode(filename.getBytes("utf-8")) + "?="; } else { //其他浏览器用的都是URLEncoder 来编码和解码 filename = URLEncoder.encode(filename, "utf-8"); } return filename; } |
4、下载的细节
4.1设置响应头的目的:
Content-Type 文件的MIME类型
Content-Disposition 响应头属性有两种类型:inline 和 attachment.
inline :将文件内容直接显示在页面 (默认)。
attachment:弹出对话框让用户下载文件。添加content-disposition头,指定了在下载框中显示的文件名称。
如:response.setHeader("Content-Disposition", "attachment;filename=白冰.jpg" );
设置了响应头IE下载框如下,
4.2 显示在下载框中的中文名称时,会出现乱码。
download.jsp
<a href="<c:url value='/DownloadServlet?path=这个杀手不太冷.avi'/>">这个杀手不太冷.avi</a><br/> <a href="<c:url value='/DownloadServlet?path=白冰.jpg'/>">白冰.jpg</a><br/> <a href="<c:url value='/DownloadServlet?path=说明文档.txt'/>">说明文档.txt</a><br/> |
* FireFox:Base64编码。
* 其他大部分浏览器:URL编码。
// 解决不同浏览器中文乱码问题,用来对下载的文件名称进行编码的! public static String filenameEncoding(String filename, HttpServletRequest request) throws IOException { String agent = request.getHeader("User-Agent"); //获取浏览器 if (agent.contains("Firefox")) { //火狐用的是BASE64Encoder 来编码和解码 filename = "=?utf-8?B?" + new BASE64Encoder().encode(filename.getBytes("utf-8")) + "?="; } else { //其他浏览器用的都是URLEncoder 来编码和解码 filename = URLEncoder.encode(filename, "utf-8"); } return filename; } |
其他通用方案:filename = new String(filename.getBytes("GBK"), "ISO-8859-1");