如何在网站中实现下载的功能?——Javaweb
文件下载实现
一、概述
下载是什么?
下载其实就是向客户端响应字节数据。
把一个文件变成字节数组,然后使用response.getOutputStream()
响应给浏览器。
下载的要求:
下载的要求其实可以简要概括成六个字:“两个头一个流 ”。
- 两个头:分别为Content-Type和Content-Disposition。
Content-Type表示的是你传递给客户端的文件的MIME类型,例如:image/pjpeg。可以通过文件名称调用ServletContext.getMimeType()
方法,得到MIME类型。
Content-Disposition的默认值为inline,表示在浏览器窗口中打开。我们要给的值是如下这种格式:attachment;filename=xxx
。在filename=
后面跟随的是显示在下载框中的文件名称。 - 一个流:就是要下载的文件数据。我们自己new一个输入流即可。
二、文件下载的示例
我们新建一个项目,并且创建一个servlet:
public class Download1Servlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/* * 准备两个头,一个流 * 1. Content-Type * 2. Content-Disposition * 3. 流:下载的文件数据 */
String filename = "E:/test.jpg";
// 两个头
// 通过文件名称获取文件MIME类型
String contentType = this.getServletContext().getMimeType(filename);
String contentDisposition = "attachment;filename=a.jpg";
// 创建一个数据流
FileInputStream input = new FileInputStream(filename);
// 接下来设置头
response.setHeader("Content-Type", contentType);
response.setHeader("Content-Disposition", contentDisposition);
// 获取绑定的客户端的流
ServletOutputStream output = response.getOutputStream();
// 把输入流的东西写入到输出流中
IOUtils.copy(input, output);
input.close();
}
}
我们直接在浏览器中访问这个servlet,我们看一下会有什么结果:
我们可以看到,弹出了一个另存为的对话框,默认的文件名就是我们设置的a.jpg。
三、有没有什么问题?
我们接着上一个示例,我们做一些更改,把文件的默认名称也就是filename=后面的内容设置为中文,我们看一下会是什么效果。
比如我们更改为:
String contentDisposition = "attachment;filename=测试用图.jpg";
我们在浏览器看一下,会是什么效果:
我们可以看到在谷歌浏览器中,文件是没有显示正确的,只显示了jpg三个字母:
我们在edge下也是不正确的:
而在IE(IE 11
)也是不正常的:
这是为什么呢?
原因和解决办法
Firefox浏览器(上面我们并没有使用该浏览器进行测试),使用的是Base64编码。而其他的大部分浏览器,使用的都是URL编码。所以才会出现上面的情况。
我们应该怎么办呢?
其实很简单,我们只需要对文件名字符串进行一个处理,
filename = new String(filename.getBytes("GBK"),"ISO-8859-1");
上面示例的代码,我们就做以下的修改:
我们再测试一下:
chrome:
工具类
我们还应该注意一点,因为浏览器的不同,使用的编码方式是不同的。我们应该先获取浏览器的版本信息,然后进行相应的转码。其实我们有一个工具类,代码很简单,如下:
package com.veeja.down.utils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import javax.servlet.http.HttpServletRequest;
import sun.misc.BASE64Encoder;
public class DownUtils {
public static String filenameEncoding(String filename, HttpServletRequest request) throws IOException {
String agent = request.getHeader("User-Agent"); //获取浏览器
if (agent.contains("Firefox")) {
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?"
+ base64Encoder.encode(filename.getBytes("utf-8"))
+ "?=";
} else if(agent.contains("MSIE")) {
filename = URLEncoder.encode(filename, "utf-8");
} else {
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}
这个工具类就可以获取浏览器的版本进行相应的转换。
使用这个工具类,我们再次改写我们以前的代码:
这样,我们再次测试一下:
也是完全OK的!
END.
还没有评论,来说两句吧...