文件下载实现
1.实现文件下载
文件下载不需要第三方组件支持,自定义完成即可
客户端
文件下载列表页面:
* a标签的href属性,直接指定对应服务器端文件的路径.
* 如果浏览器本身支持这种文件格式,直接打开.
* a标签的href属性,指定一个服务器端的程序(Servlet)的路径.
显示文件下载列表(一):
* a标签的href属性,直接指定对应服务器端文件的路径.
* 如果浏览器本身支持这种文件格式,直接打开.
* a标签的href属性,指定一个服务器端的程序(Servlet)的路径.
显示文件下载列表(一):
<h4><a href="${pageContext.request.contextPath }/downs/1.txt">1.txt</a></h4>
<h4><a href="${pageContext.request.contextPath }/downs/2.xls">2.xls</a></h4>
<h4><a href="${pageContext.request.contextPath }/downs/3.zip">3.zip</a></h4>
<h4><a href="${pageContext.request.contextPath }/downs/4.jpg">4.jpg</a></h4>
问题:
* 如果浏览器本身支持下载文件的格式,并不提供下载,而是直接显示.
* 如果浏览器本身不支持下载文件格式,提供下载功能.
显示文件下载列表(二):
<body>
<!--这里提供显示给用户查看的文件下载列表 -->
<h4><a href="${pageContext.request.contextPath }/servlet/DownServlet?filename=1.txt">1.txt</a></h4>
<h4><a href="${pageContext.request.contextPath }/servlet/DownServlet?filename=2.xls">2.xls</a></h4>
<h4><a href="${pageContext.request.contextPath }/servlet/DownServlet?filename=3.zip">3.zip</a></h4>
<h4><a href="${pageContext.request.contextPath }/servlet/DownServlet?filename=笔记.PNG">笔记.PNG</a></h4>
</body>
* 服务器端:
* 服务器端接收客户端请求下载(包含下载的文件名称).
* 查询数据库表(文件名称,文件存储路径).
* 通过文件存储路径,找到对应要下载的文件(文件输入流).
* 创建输出流(response.getOutputStream()方法).
* 调用IOUtils.copy(inputStream,outputStream).
* 服务器端接收客户端请求下载(包含下载的文件名称).
* 查询数据库表(文件名称,文件存储路径).
* 通过文件存储路径,找到对应要下载的文件(文件输入流).
* 创建输出流(response.getOutputStream()方法).
* 调用IOUtils.copy(inputStream,outputStream).
数据库:
CREATE DATABASE filedownload;
USE filedownload;
CREATE TABLE filesave(
filename VARCHAR(50),
savepath VARCHAR(200)
);
SELECT * FROM filesave;
DELETE from filesave;
INSERT INTO filesave VALUES('1.txt','F:\\apache-tomcat-8.5.0\\webapps\\filedownload\\downs\\1.txt');
INSERT INTO filesave VALUES('2.xls','F:\\apache-tomcat-8.5.0\\webapps\\filedownload\\downs\\2.xls');
INSERT INTO filesave VALUES('3.zip','F:\\apache-tomcat-8.5.0\\webapps\\filedownload\\downs\\3.zip');
INSERT INTO filesave VALUES('笔记.PNG','F:\\apache-tomcat-8.5.0\\webapps\\filedownload\\downs\\笔记.PNG');
DELETE FROM filesave WHERE filename='4.PNG';
bean:
package down;
public class FileSave {
private String filename;
private String savepath;
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public String getSavepath() {
return savepath;
}
public void setSavepath(String savepath) {
this.savepath = savepath;
}
}
DownServlet:
package down;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.sql.SQLException;
import javax.imageio.stream.FileImageInputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.io.IOUtils;
import com.mchange.util.Base64Encoder;
import com.sun.mail.util.BASE64EncoderStream;
import sun.misc.BASE64Encoder;
import utils.JDBCUtils;
//用于完成文件下载.
public class DownServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// System.out.println(new File("./").getAbsolutePath());
//1.获取客户端请求下载的文件名称
String filename = request.getParameter("filename");
//解决get方式中文乱码问题
filename = new String(filename.getBytes("ISO-8859-1"),"utf-8");
//2.通过文件名称,查询数据表
QueryRunner runner = new QueryRunner(JDBCUtils.getDataSource());
String sql = "select * from filesave where filename=?";
try {
FileSave filesave = runner.query(sql, new BeanHandler<FileSave>(FileSave.class), filename);
//3.通过查询到的保存路径,读取具体文件
// String path = filesave.getSavepath();
//读取文件
InputStream in = new FileInputStream(new File(filesave.getSavepath()));
//4.获取服务端的响应输出流
OutputStream out = response.getOutputStream();
//解决下载文件名的中文乱码
//获取客户端请求头的User-Agent:
String userAgent = request.getHeader("User-Agent");
//不同浏览器有不同的处理:
if(userAgent.contains("MSIE")){
//IE浏览器:
filename = URLEncoder.encode(filename,"utf-8");
filename = filename.replace("+", "");
}else{
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
}
//通知浏览器文件是需要下载的,而不是直接显示:
response.setContentType(getServletContext().getMimeType(filename));
response.setHeader("Content-Disposition", "attachment;filename="+filename);
//5.利用IOUtils工具类的copy方法
IOUtils.copy(in, out);
in.close();
out.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
2.中文乱码解决
下载文件功能实现后,还需要解决中文乱码问题。由于下载页面中的文件名是使用GET方式提交请求的,所以可以使用如下代码解决:
filename = new String(filename.getBytes("ISO-8859-1"),"UTF-8");
而上述代码只能解决服务器端接收客户端请求时参数的中文乱码问题,但是点击文件下载时的文件名称依旧是乱码的。这个问题是由于浏览器本身的问题,不同浏览器的解决方式不同:
IE浏览器:使用URL编码:filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
其他浏览器,使用BASE64编码:
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
可以通过Http请求协议的请求头中的“User-Agent”内容,判断客户端当前使用的浏览器是哪个产品:
String agent = request.getHeader("User-Agent");
if(agent.contains("MSIE")){
// IE浏览器,使用URL编码
}else{
// 其他浏览器,使用BASE64编码
}
注意:
response.setContentType(getServletContext().getMimeType(filename));
response.setHeader("Content-Disposition", "attachment;filename="+filename);
解决下载中的中文乱码问题:
* 解决请求参数中文乱码:
filename = new String(filename.getBytes("ISO-8859-1"),"utf-8");
解决下载文件名称中文乱码:
String userAgent = request.getHeader("User-Agent");
if(userAgent.contains("MSIE")){
/ IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
}else{
// 其他浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
}