java web--文件上传下载 (1)

 1.文件上传分析

文件上传: 就是将客户端的数据发送到服务器上
文件上传要求:
            浏览器端要求:
                                    1.表单提交方式 post
                                    2.提供文件上传框(组件) input type="file"
                                    3.表单entype属性必须为 multipart/form-data
             服务器端要求:
                                    request.getInputStream()
             注意:
                            若表单使用了 multipart/form-data ,使用原生request.getParameter去获取参数的时候都为null ,请求头有请求类型context-type:multipart/form-data 

                           因此要用流接收  ServletInputStream servletInputStream=request.getInputStream();

                           

                             由于解析太过复杂,因此 使用工具类或者框架去解析用户上传的内容
                               commons-fileupload,struts(底层:commons-fileupload),serlvet3.0
                              apache出品的一款专门处理文件上传的工具类  commons-fileupload

              上传注意问题:
                                1.文件名称  浏览器不同,有可能获取的名称不同, 1.txt 或者 G:1.txt 
                                2.文件重名  给文件来一个随机名称 uuid方式  毫米值+三个随机数
                                  数据库中可以存放多个字段: 文件名称和文件路径
                                 文件名称:身份证正面.jpg
                                 文件路径:g:123123123423sfsf.jpg
                                 文件下载:  response.setHeader("content-disposition","attachment;filename="+真实名称);
                                3.文件安全(fastDFS框架)  安全目录:web-inf meta-inf 项目之外的目录
                                   不安全目录:项目目录(除去web-inf和meta-inf)
                               4.目录分离常用的方式:解决一个文件夹放1万个数据下载慢的问题
                                  按用户划分、按时间划分、按数量划分、随机划分 
2.文件上传实现 

              

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <form action="${pageContext.request.contextPath}/fileServlet" method="post" enctype="multipart/form-data"> 
        <input type="file" name="file1"/>
        <input type="file" name="file2"/>
        <input type="text" name="username"/>
        <input type="submit" value="提交">
    </form>      
</body>
</html>
index.jsp 上传页面
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
  <head>
    <title>消息提示</title>
  </head>
  
  <body>
        ${message}
  </body>
</html>
message 上传成功返回的页面
package com.zwj.demo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;


/**
 * 上传功能
 */
public class fileServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
                    //得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
                    System.out.println(this.getServletName()); 
                    System.out.println(this.getServletInfo());
                    String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
                    File file = new File(savePath);
                    //判断上传文件的保存目录是否存在
                    if (!file.exists() && !file.isDirectory()) {
                        System.out.println(savePath+"目录不存在,需要创建");
                        //创建目录
                        file.mkdir();
                    }
                    //消息提示
                    String message = "";
                    try{
                        //使用Apache文件上传组件处理文件上传步骤:
                        //1、创建一个DiskFileItemFactory工厂
                        DiskFileItemFactory factory = new DiskFileItemFactory();
                        //2、创建一个文件上传解析器
                        ServletFileUpload upload = new ServletFileUpload(factory);
                         //解决上传文件名的中文乱码
                        upload.setHeaderEncoding("UTF-8"); 
                        //3、判断提交上来的数据是否是上传表单的数据
                        if(!ServletFileUpload.isMultipartContent(request)){
                            //按照传统方式获取数据
                            return;
                        }
                        //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
                        List<FileItem> list = upload.parseRequest(request);
                        for(FileItem item : list){
                            //如果fileitem中封装的是普通输入项的数据
                            if(item.isFormField()){
                                String name = item.getFieldName();
                                //解决普通输入项的数据的中文乱码问题
                                String value = item.getString("UTF-8");
                                //value = new String(value.getBytes("iso8859-1"),"UTF-8");
                                System.out.println(name + "=" + value);
                            }else{//如果fileitem中封装的是上传文件
                                //得到上传的文件名称,
                                String filename = item.getName();
                                System.out.println(filename);
                                if(filename==null || filename.trim().equals("")){
                                    continue;
                                }
                                //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:a1.txt,而有些只是单纯的文件名,如:1.txt
                                //处理获取到的上传文件的文件名的路径部分,只保留文件名部分
                                filename = filename.substring(filename.lastIndexOf("\")+1);
                                //获取item中的上传文件的输入流
                                InputStream in = item.getInputStream();
                                //创建一个文件输出流
                                FileOutputStream out = new FileOutputStream(savePath + "\" + filename);
                                //创建一个缓冲区
                                byte buffer[] = new byte[1024];
                                //判断输入流中的数据是否已经读完的标识
                                int len = 0;
                                //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
                                while((len=in.read(buffer))>0){
                                    //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\" + filename)当中
                                    out.write(buffer, 0, len);
                                }
                                //关闭输入流
                                in.close();
                                //关闭输出流
                                out.close();
                                //删除处理文件上传时生成的临时文件
                                item.delete();
                                message = "文件上传成功!";
                            }
                        }
                    }catch (Exception e) {
                        message= "文件上传失败!";
                        e.printStackTrace();
                        
                    }
                    request.setAttribute("message",message);
                    request.getRequestDispatcher("/message.jsp").forward(request, response);
        }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
         /*
          * 表单提交时如果没有加 enctype="multipart/form-data",可以接受,但只是name的属性值
          * 加上后,使用request.getParameter("username") 为 null;
          * 因此要用流接收
          */
         //String username=request.getParameter("username");
          //String filename=request.getParameter("filesname");
         //  ServletInputStream servletInputStream=request.getInputStream();
         // System.out.println(servletInputStream);
          //org.apache.catalina.connector.CoyoteInputStream@18906123
          this.doGet(request, response);
        
    }
}
fileServlet 上传功能控制类

   2.2、上述的代码虽然可以成功将文件上传到服务器上面的指定目录中,但是文件上传功能有许多需要注意的小细节问题,以下的几点特别注意的

  1、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。

  2、为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。

  3、为防止一个目录下面出现太多文件,要使用hash算法打散存储。

  4、要限制上传文件的最大值。

  5、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。

  针对上述提出的5点细节问题,我们来改进一下UploadHandleServlet,改进后的代码如下:

package com.zwj.demo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;


/**
 * 上传下载功能
 */
public class fileServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    @Override
      public void doGet(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
                 //得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
                 String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
                 //上传时生成的临时文件保存目录
                 String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
                 File tmpFile = new File(tempPath);
                 if (!tmpFile.exists()) {
                     //创建临时目录
                     tmpFile.mkdir();
                 }
                 //消息提示
                 String message = "";
                 try{
                     //使用Apache文件上传组件处理文件上传步骤:
                     //1、创建一个DiskFileItemFactory工厂
                     DiskFileItemFactory factory = new DiskFileItemFactory();
                     //设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。
                     factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB
                     //设置上传时生成的临时文件的保存目录
                     factory.setRepository(tmpFile);
                     //2、创建一个文件上传解析器
                     ServletFileUpload upload = new ServletFileUpload(factory);
                     //监听文件上传进度
                     upload.setProgressListener(new ProgressListener(){
                         public void update(long pBytesRead, long pContentLength, int arg2) {
                             System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead);
                             /**
                              * 文件大小为:14608,当前已处理:4096
                                 文件大小为:14608,当前已处理:7367
                                 文件大小为:14608,当前已处理:11419
                                 文件大小为:14608,当前已处理:14608
                              */
                         }
                     });
                      //解决上传文件名的中文乱码
                     upload.setHeaderEncoding("UTF-8"); 
                     //3、判断提交上来的数据是否是上传表单的数据
                     if(!ServletFileUpload.isMultipartContent(request)){
                         //按照传统方式获取数据
                         return;
                     }
                     
                     //设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
                     upload.setFileSizeMax(1024*1024);
                     //设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB
                     upload.setSizeMax(1024*1024*10);
                     //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
                     List<FileItem> list = upload.parseRequest(request);
                     for(FileItem item : list){
                         //如果fileitem中封装的是普通输入项的数据
                         if(item.isFormField()){
                             String name = item.getFieldName();
                             //解决普通输入项的数据的中文乱码问题
                             String value = item.getString("UTF-8");
                             //value = new String(value.getBytes("iso8859-1"),"UTF-8");
                             System.out.println(name + "=" + value);
                         }else{//如果fileitem中封装的是上传文件
                             //得到上传的文件名称,
                             String filename = item.getName();
                             System.out.println(filename);
                             if(filename==null || filename.trim().equals("")){
                                 continue;
                             }
                             //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:a1.txt,而有些只是单纯的文件名,如:1.txt
                             //处理获取到的上传文件的文件名的路径部分,只保留文件名部分
                             filename = filename.substring(filename.lastIndexOf("\")+1);
                             //得到上传文件的扩展名
                             String fileExtName = filename.substring(filename.lastIndexOf(".")+1);
                             //如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法
                             System.out.println("上传的文件的扩展名是:"+fileExtName);
                             //获取item中的上传文件的输入流
                             InputStream in = item.getInputStream();
                             //得到文件保存的名称
                             String saveFilename = makeFileName(filename);
                             //得到文件的保存目录
                             String realSavePath = makePath(saveFilename, savePath);
                             System.out.println(realSavePath + "\" + saveFilename);
                             //创建一个文件输出流
                             FileOutputStream out = new FileOutputStream(realSavePath + "\" + saveFilename);
                             //创建一个缓冲区
                             byte buffer[] = new byte[1024];
                             //判断输入流中的数据是否已经读完的标识
                             int len = 0;
                             //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
                             while((len=in.read(buffer))>0){
                                 //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\" + filename)当中
                                 out.write(buffer, 0, len);
                             }
                             //关闭输入流
                             in.close();
                             //关闭输出流
                             out.close();
                             //删除处理文件上传时生成的临时文件
                             //item.delete();
                             message = "文件上传成功!";
                         }
                     }
                 }catch (FileUploadBase.FileSizeLimitExceededException e) {
                     e.printStackTrace();
                     request.setAttribute("message", "单个文件超出最大值!!!");
                     request.getRequestDispatcher("/message.jsp").forward(request, response);
                     return;
                 }catch (FileUploadBase.SizeLimitExceededException e) {
                     e.printStackTrace();
                     request.setAttribute("message", "上传文件的总的大小超出限制的最大值!!!");
                     request.getRequestDispatcher("/message.jsp").forward(request, response);
                     return;
                 }catch (Exception e) {
                     message= "文件上传失败!";
                     e.printStackTrace();
                 }
                 request.setAttribute("message",message);
                 request.getRequestDispatcher("/message.jsp").forward(request, response);
     }
     
     /**
     * @Method: makeFileName
     * @Description: 生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称
     * @param filename 文件的原始名称
     * @return uuid+"_"+文件的原始名称
     */ 
     private String makeFileName(String filename){  //2.jpg
         //为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
         return UUID.randomUUID().toString() + "_" + filename;
     }
     
     /**
      * 为防止一个目录下面出现太多文件,要使用hash算法打散存储
     * @Method: makePath
     * @Description: 
     * @param filename 文件名,要根据文件名生成存储目录
     * @param savePath 文件存储路径
     * @return 新的存储目录
     */ 
     private String makePath(String filename,String savePath){
         //得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址
         int hashcode = filename.hashCode();
         int dir1 = hashcode&0xf;  //0--15
         int dir2 = (hashcode&0xf0)>>4;  //0-15
         //构造新的保存目录
         String dir = savePath + "\" + dir1 + "\" + dir2;  //upload23  upload35
         //File既可以代表文件也可以代表目录
         File file = new File(dir);
         //如果目录不存在
         if(!file.exists()){
             //创建目录
             file.mkdirs();
         }
         return dir;
     }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
         /*
          * 表单提交时如果没有加 enctype="multipart/form-data",可以接受,但只是name的属性值
          * 加上后,使用request.getParameter("username") 为 null;
          * 因此要用流接收
          */
         //String username=request.getParameter("username");
          //String filename=request.getParameter("filesname");
         //  ServletInputStream servletInputStream=request.getInputStream();
         // System.out.println(servletInputStream);
          //org.apache.catalina.connector.CoyoteInputStream@18906123
          this.doGet(request, response);
        
    }
}
/*文件大小为:87999,当前已处理:4096
文件大小为:87999,当前已处理:7600
文件大小为:87999,当前已处理:11652
文件大小为:87999,当前已处理:15200
文件大小为:87999,当前已处理:19252
文件大小为:87999,当前已处理:22800
文件大小为:87999,当前已处理:26852
文件大小为:87999,当前已处理:30400
文件大小为:87999,当前已处理:34452
文件大小为:87999,当前已处理:38000
文件大小为:87999,当前已处理:42052
文件大小为:87999,当前已处理:45600
文件大小为:87999,当前已处理:49652
文件大小为:87999,当前已处理:53200
文件大小为:87999,当前已处理:57252
文件大小为:87999,当前已处理:60800
文件大小为:87999,当前已处理:64852
文件大小为:87999,当前已处理:68400
文件大小为:87999,当前已处理:72452
文件大小为:87999,当前已处理:76000
文件大小为:87999,当前已处理:80052
文件大小为:87999,当前已处理:83600
文件大小为:87999,当前已处理:87652
文件大小为:87999,当前已处理:87999
下载必看.doc
上传的文件的扩展名是:doc
D:workspace.metadata.pluginsorg.eclipse.wst.server.core	mp0wtpwebappsfileUploadWEB-INFupload101ee18e49-8fad-434e-aad7-6c2e08284cfc_下载必看.doc
CookUtils.java
上传的文件的扩展名是:java
D:workspace.metadata.pluginsorg.eclipse.wst.server.core	mp0wtpwebappsfileUploadWEB-INFupload11a0fab1db-9e30-4475-8f96-c42f4c8714ae_CookUtils.java
username=name
*/
fileServlet 上传功能修改后的

 3.文件下载

                          

     首先 http://localhost:8080/fileUpload/listFileServlet 得到服务器可以下载文件  注:用jstl标签 必须有jstl.jar / standard.jar 两个jar包

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core"  prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
     <title>下载文件显示页面</title>
   </head>
   
   <body>
       <!-- 遍历Map集合    k :a0fab1db-9e30-4475-8f96-c42f4c8714ae_CookUtils.java  
          v:CookUtils.java
           -->
     <c:forEach var="me" items="${fileNameMap}">
         <c:url value="/downLoadServlet" var="downurl">
             <c:param name="filename" value="${me.key}"></c:param>
         </c:url>
         ${me.value}<a href="${downurl}">下载</a>
         <br/>
     </c:forEach>
   </body>
 </html>
listfile.jsp
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>fileUpload</display-name>
   <!--上传的servlet-->
   <servlet>
         <servlet-name>user</servlet-name>
         <servlet-class>com.zwj.demo.fileServlet</servlet-class>
   </servlet>
  <servlet-mapping>
         <servlet-name>user</servlet-name>
      <url-pattern>/fileServlet</url-pattern>      
  </servlet-mapping>
   <!--读取可下载文件的servlet-->
   <servlet>
      <servlet-name>ListFileServlet</servlet-name>
      <servlet-class>com.zwj.demo.ListFileServlet</servlet-class>
   </servlet>
  <servlet-mapping>
      <servlet-name>ListFileServlet</servlet-name>
     <url-pattern>/listFileServlet</url-pattern>
  </servlet-mapping> 
<!--下载的servlet-->
  <servlet>
      <servlet-name>DownLoadServlet</servlet-name>
      <servlet-class>com.zwj.demo.DownLoadServlet</servlet-class>
</servlet>
 
<servlet-mapping>
      <servlet-name>DownLoadServlet</servlet-name>
      <url-pattern>/downLoadServlet</url-pattern>
</servlet-mapping>
 
  
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  
</web-app>
web.xml
package com.zwj.demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DownLoadServlet extends HttpServlet {
     public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            //得到要下载的文件名
            String fileName = request.getParameter("filename");  //23239283-92489-阿凡达.avi
            fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8");
            //上传的文件都是保存在/WEB-INF/upload目录下的子目录当中
            String fileSaveRootPath=this.getServletContext().getRealPath("/WEB-INF/upload");
            //通过文件名找出文件的所在目录
            String path = findFileSavePathByFileName(fileName,fileSaveRootPath);
            //得到要下载的文件
            File file = new File(path + "\" + fileName);
            //如果文件不存在
            if(!file.exists()){
                request.setAttribute("message", "您要下载的资源已被删除!!");
                request.getRequestDispatcher("/message.jsp").forward(request, response);
                return;
            }
            //处理文件名
            String realname = fileName.substring(fileName.indexOf("_")+1);
            //设置响应头,控制浏览器下载该文件
            response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
            //读取要下载的文件,保存到文件输入流
            FileInputStream in = new FileInputStream(path + "\" + fileName);
            //创建输出流
            OutputStream out = response.getOutputStream();
            //创建缓冲区
            byte buffer[] = new byte[1024];
            int len = 0;
            //循环将输入流中的内容读取到缓冲区当中
            while((len=in.read(buffer))>0){
                //输出缓冲区的内容到浏览器,实现文件下载
                out.write(buffer, 0, len);
            }
            //关闭文件输入流
            in.close();
            //关闭输出流
            out.close();
        }
        
        /**
        * @Method: findFileSavePathByFileName
        * @Description: 通过文件名和存储上传文件根目录找出要下载的文件的所在路径
        * @param filename 要下载的文件名
        * @param saveRootPath 上传文件保存的根目录,也就是/WEB-INF/upload目录
        * @return 要下载的文件的存储目录
        */ 
        public String findFileSavePathByFileName(String filename,String saveRootPath){
            int hashcode = filename.hashCode();
            int dir1 = hashcode&0xf;  //0--15
            int dir2 = (hashcode&0xf0)>>4;  //0-15
            String dir = saveRootPath + "\" + dir1 + "\" + dir2;  //upload23  upload35
            File file = new File(dir);
            if(!file.exists()){
                //创建目录
                file.mkdirs();
            }
            return dir;
        }
        
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);
        }
}
DownLoadServlet  下载文件servlet
 1package me.gacl.web.controller;
 2 
 3 import java.io.File;
 4 import java.io.FileInputStream;
 5 import java.io.IOException;
 6 import java.io.OutputStream;
 7 import java.net.URLEncoder;
 8 import javax.servlet.ServletException;
 9 import javax.servlet.http.HttpServlet;
10 import javax.servlet.http.HttpServletRequest;
11 import javax.servlet.http.HttpServletResponse;
12 
13 public class DownLoadServlet extends HttpServlet {
14 
15     
16     public void doGet(HttpServletRequest request, HttpServletResponse response)
17             throws ServletException, IOException {
18         //得到要下载的文件名
19         String fileName = request.getParameter("filename");  //23239283-92489-阿凡达.avi
20         fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8");
21         //上传的文件都是保存在/WEB-INF/upload目录下的子目录当中
22         String fileSaveRootPath=this.getServletContext().getRealPath("/WEB-INF/upload");
23         //通过文件名找出文件的所在目录
24         String path = findFileSavePathByFileName(fileName,fileSaveRootPath);
25         //得到要下载的文件
26         File file = new File(path + "\" + fileName);
27         //如果文件不存在
28         if(!file.exists()){
29             request.setAttribute("message", "您要下载的资源已被删除!!");
30             request.getRequestDispatcher("/message.jsp").forward(request, response);
31             return;
32         }
33         //处理文件名
34         String realname = fileName.substring(fileName.indexOf("_")+1);
35         //设置响应头,控制浏览器下载该文件
36         response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
37         //读取要下载的文件,保存到文件输入流
38         FileInputStream in = new FileInputStream(path + "\" + fileName);
39         //创建输出流
40         OutputStream out = response.getOutputStream();
41         //创建缓冲区
42         byte buffer[] = new byte[1024];
43         int len = 0;
44         //循环将输入流中的内容读取到缓冲区当中
45         while((len=in.read(buffer))>0){
46             //输出缓冲区的内容到浏览器,实现文件下载
47             out.write(buffer, 0, len);
48         }
49         //关闭文件输入流
50         in.close();
51         //关闭输出流
52         out.close();
53     }
54     
55     /**
56     * @Method: findFileSavePathByFileName
57     * @Description: 通过文件名和存储上传文件根目录找出要下载的文件的所在路径
58     * @Anthor:孤傲苍狼
59     * @param filename 要下载的文件名
60     * @param saveRootPath 上传文件保存的根目录,也就是/WEB-INF/upload目录
61     * @return 要下载的文件的存储目录
62     */ 
63     public String findFileSavePathByFileName(String filename,String saveRootPath){
64         int hashcode = filename.hashCode();
65         int dir1 = hashcode&0xf;  //0--15
66         int dir2 = (hashcode&0xf0)>>4;  //0-15
67         String dir = saveRootPath + "\" + dir1 + "\" + dir2;  //upload23  upload35
68         File file = new File(dir);
69         if(!file.exists()){
70             //创建目录
71             file.mkdirs();
72         }
73         return dir;
74     }
75     
76     public void doPost(HttpServletRequest request, HttpServletResponse response)
77             throws ServletException, IOException {
78         doGet(request, response);
79     }
80 }
DownLoadServlet  得到下载目录的servlet 

        

原文地址:https://www.cnblogs.com/ou-pc/p/7894986.html