文件下载的本质
通过输出流将服务器上磁盘上的一个文件拷贝(写)到客户端磁盘上
servlet下载文件步骤
1.将文件名称转换成为utf-8
2.将文件转换成流
3.处理不同浏览器中文乱码
火狐浏览器要求中文文件名以Base64编码,其它浏览器一般以URLEncoder编码,所以需要根据浏览器类型分别处理
4.设置下载时候的响应头(Content-Type和Content-Disposition)
注意:如果content-type是通过后缀名获取的话,个别谷歌浏览器版本可能会直接打开文本或者图片,而不是下载的形式
5.通过输出流将文件回写到浏览器完成下载.
通过servlet实现文件下载
download.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>文件下载的列表页面</h1>
<h3>手动编码方式下载</h3>
<a href="/DownloadDemo_Servlet/down?filename=test.txt">test.txt</a><br/>
<a href="/DownloadDemo_Servlet/down?filename=girl.jpg">girl.jpg</a><br/>
<a href="/DownloadDemo_Servlet/down?filename=hello.zip">hello.zip</a><br/>
<a href="/DownloadDemo_Servlet/down?filename=美女.jpg">美女.jpg</a><br/>
</body>
</html>
下载中文名称文件
IE浏览器下载中文文件的时候采用的URL的编码.
Firefox浏览器下载中文文件的时候采用的是Base64的编码.
/**
*将文件名称进行base64转换
*/
public String base64EncodeFileName(String fileName) {
BASE64Encoder base64Encoder = new BASE64Encoder();
try {
return "=?UTF-8?B?"
+ new String(base64Encoder.encode(fileName
.getBytes("UTF-8"))) + "?=";
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
实例代码
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = -8967294054290769951L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//------1.获取要下载的文件名称(需要处理如果参数为中文的情况)--------
String filename = req.getParameter("filename");
//------------------------------------------------------------------
//------2.将该文件获取到并转换成输入流------------------------------
String fileAbsPath = getServletContext().getRealPath("/download/"+filename);
InputStream is = new FileInputStream(fileAbsPath);
//------------------------------------------------------------------
//注意:提前获取mimeType,不然文件名经过编码后再获取就会出问题
String mimeType = getServletContext().getMimeType(filename);
//------3.将文件名称处理成为被浏览器解析的名称----------------------
String userAgent = req.getHeader("User-Agent");
if(userAgent.contains("FireFox")) {
filename = base64EncodeFileName(filename);
}else {
filename = URLEncoder.encode(filename, "utf-8");
}
//------------------------------------------------------------------
//------4.设置响应头 content-type-----------------------------------
resp.setHeader("Content-Type", mimeType);
resp.setHeader("Content-Disposition", "attachment;filename="+filename);
//------------------------------------------------------------------
//------5.通过输出流将文件回写到浏览器完成下载----------------------
OutputStream os = resp.getOutputStream();
int len = 0;
byte[] b = new byte[1024];
while((len = is.read(b))!= -1){
os.write(b, 0, len);
}
is.close();
//------------------------------------------------------------------
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
public String base64EncodeFileName(String fileName) {
BASE64Encoder base64Encoder = new BASE64Encoder();
try {
return "=?UTF-8?B?" + new String(base64Encoder.encode(fileName.getBytes("UTF-8"))) + "?=";
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
解决谷歌个别版本下载文本文件和图片直接打开的办法
将Content-Type的头的值写成application/x-msdownload即可
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//------1.获取要下载的文件名称(需要处理如果参数为中文的情况)--------
String filename = new String(req.getParameter("filename").getBytes("ISO-8859-1"),"utf-8");
//------------------------------------------------------------------
//------2.将该文件获取到并转换成输入流------------------------------
String fileAbsPath = getServletContext().getRealPath("/download/"+filename);
InputStream is = new FileInputStream(fileAbsPath);
//------------------------------------------------------------------
//------3.将文件名称处理成为被浏览器解析的名称----------------------
String userAgent = req.getHeader("User-Agent");
if(userAgent.contains("FireFox")) {
filename = base64EncodeFileName(filename);
}else {
filename = URLEncoder.encode(filename, "utf-8");
}
//------------------------------------------------------------------
//------4.设置响应头 content-type-----------------------------------
resp.setHeader("Content-Type", "application/x-msdownload;");
resp.setHeader("Content-Disposition", "attachment;filename="+filename);
//------------------------------------------------------------------
//------5.通过输出流将文件回写到浏览器完成下载----------------------
OutputStream os = resp.getOutputStream();
int len = 0;
byte[] b = new byte[1024];
while((len = is.read(b))!= -1){
os.write(b, 0, len);
}
is.close();
//------------------------------------------------------------------
}
|
|