利用Servlet实现文件的下载功能,今天就利用上班时间做了一个小小的demo.在这里先说明一下:在实现Servlet下载的时候,大家可能会习惯性的在html页面直接写一个URL链接,如:
http://127.0.0.1:7001/TestFileUpload/fileDownLoadServlet?filename=mm.txt&file_path=/day1/xiu.txt。这是一种很不友好的方式,它容易暴露主机系统的文件路径,很不安全,别有用心的人如果知道了主机系统文件的目录结构,就很轻易的在浏览器的地址栏中输入这样的URL链接随意的下载系统文件。所以那种方式我就不建议采用了.
首先写一个Servlet下载类,为了安全,我采用了post提交方式。
public class FileDownLoadServlet extends HttpServlet{
private static final long serialVersionUID = 1L;
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
//获得文件名
String fileName=request.getParameter("filename");
//获得文件所在的路径
String filePath=request.getParameter("file_path");
download(fileName,filePath,request,response);
}
public HttpServletResponse download(String fileName,String filePath,HttpServletRequest request, HttpServletResponse response) {
try {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
ServletContext application=this.getServletContext();
//application.getRealPath("/") 得到web应用的绝对路径
File file = new File(application.getRealPath("/")+filePath);
System.out.println("request path: "+application.getRealPath("/"));
//返回URL请求的URL路径
System.out.println("getContextPath :"+request.getContextPath());
// 以流的形式下载文件。
InputStream fis = new BufferedInputStream(new FileInputStream(file));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
// 清空response
response.reset();
// 设置response的Header
response.addHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("utf-8"),"ISO-8859-1"));
response.addHeader("Content-Length", "" + file.length());
response.setContentType("application/octet-stream");
OutputStream out = new BufferedOutputStream(response.getOutputStream());
out.write(buffer);
out.flush();
out.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return response;
}
}
之所以采用post提交方式,是因为get方式非常的不安全(虽然get()方式比较方便、直观)。
之后就配置web.xnl文件,把Servlet配置进去.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>attach</servlet-name>
<servlet-class>com.future.zfs.util.FileDownLoadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>attach</servlet-name>
<url-pattern>/attach</url-pattern>
</servlet-mapping>
</web-app>
最后就写一个test.html文件啦.采用了URL链接方式提交表单,因为form表单自身的type="submit"方式在网页显示的是一个按钮,呵呵,本来下载应该是一个URL链接才是,个人想法。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>test.html</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
<script type="text/javascript">
function download(){
document.getElementById("form").submit();
}
</script>
</head>
<body>
<form id="form" action="attach" method="post">
<input type="hidden" name="filename" value="mm.txt" />
<input type="hidden" name="file_path" value="/day1/xiu.txt"/>
</form>
<a href="javascript:void(0)" οnclick="download()">文件下载</a>
</body>
</html>
当你把鼠标移到文件下载这个链接上时,在浏览器的状态栏显示的时:javascript:void(0) ,而不是文件的系统路径了。就算知道了文件路径在浏览器的地址输入地址也不会进行下载.。因为在地址栏的都是get()方式,而我们在下载类里写的是Post()方法。
好了,一个安全下载的小demo就这样完成了.关于文件名的中文问题,我还没有找到解决办法,有知道的分享下呗.
为了方便大家,我把我做的demo路径贴出来: