利用Servlet实现文件安全下载

利用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)" onclick="download()">文件下载</a>
  </body>
</html> 

 当你把鼠标移到文件下载这个链接上时,在浏览器的状态栏显示的时:javascript:void(0)  ,而不是文件的系统路径了。就算知道了文件路径在浏览器的地址输入地址也不会进行下载.。因为在地址栏的都是get()方式,而我们在下载类里写的是Post()方法。

好了,一个安全下载的小demo就这样完成了.关于文件名的中文问题,我还没有找到解决办法,有知道的分享下呗.

为了方便大家,我把我做的demo路径贴出来:

原文地址:https://www.cnblogs.com/wuyida/p/6300441.html