java文件上传和下载

来源:互联网 发布:教你化妆软件 编辑:程序博客网 时间:2024/06/11 19:06
  • 简介

  文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到本地。

  对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件。这个common-fileupload上传组件的jar包可以去apache官网上面下载,也可以在strutslib文件夹下面找到,struts上传的功能就是基于这个实现的。common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。

  • 文件上传

  1、文件上传页面和消息提示页面

  upload.jsp页面的代码如下:

 

复制代码
 1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <!DOCTYPE HTML> 3 <html> 4   <head> 5     <title>文件上传</title> 6    </head> 7    8    <body> 9      <form action="${pageContext.request.contextPath}/servlet/uploadHandleServlet2" enctype="multipart/form-data" method="post"         上传用户:<input type="text" name="username"><br/>10          上传文件1:<input type="file" name="file1"><br/>11          上传文件2:<input type="file" name="file2"><br/>12          <input type="submit" value="提交">13      </form>14    </body>15 </html>
复制代码

 

  在文件上传的页面要用enctype="multipart/form-data" method="post"来表示进行文件上传。

  2、处理文件上传的Servlet

 

复制代码
 1 public class UploadHandleServlet extends HttpServlet{ 2  3     @Override 4     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 5         //得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全 6         String savePath = this.getServletContext().getRealPath("/WEB-INF/upload"); 7         File file = new File(savePath); 8         if(!file.exists()&&!file.isDirectory()){ 9             System.out.println("目录或文件不存在!");10             file.mkdir();11         }12         //消息提示13         String message = "";14         try {15             //使用Apache文件上传组件处理文件上传步骤:16             //1、创建一个DiskFileItemFactory工厂17             DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();18             //2、创建一个文件上传解析器19             ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory);20             //解决上传文件名的中文乱码21             fileUpload.setHeaderEncoding("UTF-8");22             //3、判断提交上来的数据是否是上传表单的数据23             if(!fileUpload.isMultipartContent(request)){24                 //按照传统方式获取数据25                 return;26             }27             //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项28             List<FileItem> list = fileUpload.parseRequest(request);29             for (FileItem item : list) {30                 //如果fileitem中封装的是普通输入项的数据31                 if(item.isFormField()){32                     String name = item.getFieldName();33                     //解决普通输入项的数据的中文乱码问题34                     String value = item.getString("UTF-8");35                     String value1 = new String(name.getBytes("iso8859-1"),"UTF-8");36                     System.out.println(name+"  "+value);37                     System.out.println(name+"  "+value1);38                 }else{39                     //如果fileitem中封装的是上传文件,得到上传的文件名称,40                     String fileName = item.getName();41                     System.out.println(fileName);42                     if(fileName==null||fileName.trim().equals("")){43                         continue;44                     }45                     //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt46                     //处理获取到的上传文件的文件名的路径部分,只保留文件名部分47                     fileName = fileName.substring(fileName.lastIndexOf(File.separator)+1);48                     //获取item中的上传文件的输入流49                     InputStream is = item.getInputStream();50                     //创建一个文件输出流51                     FileOutputStream fos = new FileOutputStream(savePath+File.separator+fileName);52                     //创建一个缓冲区53                     byte buffer[] = new byte[1024];54                     //判断输入流中的数据是否已经读完的标识55                     int length = 0;56                     //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据57                     while((length = is.read(buffer))>0){58                         //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中59                         fos.write(buffer, 0, length);60                     }61                     //关闭输入流62                     is.close();63                     //关闭输出流64                     fos.close();65                     //删除处理文件上传时生成的临时文件66                     item.delete();67                     message = "文件上传成功";68                 }69             }70         } catch (FileUploadException e) {71             // TODO Auto-generated catch block72             e.printStackTrace();73             message = "文件上传失败";74         }75         request.setAttribute("message",message);76         request.getRequestDispatcher("/message.jsp").forward(request, response);77     }78 79     @Override80     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {81         doGet(request, response);82     }83     84 }
复制代码

 

  3、文件上传的细节

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

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

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

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

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

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

  4、改进后的servlet

 

复制代码
  1 public class UploadHandleServlet1 extends HttpServlet{  2   3     @Override  4     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  5         //得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全  6         String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");  7         //上传时生成的临时文件保存目录  8         String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");  9         File file = new File(tempPath); 10         if(!file.exists()&&!file.isDirectory()){ 11             System.out.println("目录或文件不存在!"); 12             file.mkdir(); 13         } 14         //消息提示 15         String message = ""; 16         try { 17             //使用Apache文件上传组件处理文件上传步骤: 18             //1、创建一个DiskFileItemFactory工厂 19             DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory(); 20             //设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。 21             diskFileItemFactory.setSizeThreshold(1024*100); 22             //设置上传时生成的临时文件的保存目录 23             diskFileItemFactory.setRepository(file); 24             //2、创建一个文件上传解析器 25             ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory); 26             //解决上传文件名的中文乱码 27             fileUpload.setHeaderEncoding("UTF-8"); 28             //监听文件上传进度 29             fileUpload.setProgressListener(new ProgressListener(){ 30                 public void update(long pBytesRead, long pContentLength, int arg2) { 31                     System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead); 32                 } 33             }); 34             //3、判断提交上来的数据是否是上传表单的数据 35             if(!fileUpload.isMultipartContent(request)){ 36                 //按照传统方式获取数据 37                 return; 38             } 39             //设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB 40             fileUpload.setFileSizeMax(1024*1024); 41             //设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB 42             fileUpload.setSizeMax(1024*1024*10); 43             //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项 44             List<FileItem> list = fileUpload.parseRequest(request); 45             for (FileItem item : list) { 46                 //如果fileitem中封装的是普通输入项的数据 47                 if(item.isFormField()){ 48                     String name = item.getFieldName(); 49                     //解决普通输入项的数据的中文乱码问题 50                     String value = item.getString("UTF-8"); 51                     String value1 = new String(name.getBytes("iso8859-1"),"UTF-8"); 52                     System.out.println(name+"  "+value); 53                     System.out.println(name+"  "+value1); 54                 }else{ 55                     //如果fileitem中封装的是上传文件,得到上传的文件名称, 56                     String fileName = item.getName(); 57                     System.out.println(fileName); 58                     if(fileName==null||fileName.trim().equals("")){ 59                         continue; 60                     } 61                     //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt 62                     //处理获取到的上传文件的文件名的路径部分,只保留文件名部分 63                     fileName = fileName.substring(fileName.lastIndexOf(File.separator)+1); 64                     //得到上传文件的扩展名 65                     String fileExtName = fileName.substring(fileName.lastIndexOf(".")+1); 66                     if("zip".equals(fileExtName)||"rar".equals(fileExtName)||"tar".equals(fileExtName)||"jar".equals(fileExtName)){ 67                         request.setAttribute("message", "上传文件的类型不符合!!!"); 68                         request.getRequestDispatcher("/message.jsp").forward(request, response); 69                         return; 70                     } 71                     //如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法 72                     System.out.println("上传文件的扩展名为:"+fileExtName); 73                     //获取item中的上传文件的输入流 74                     InputStream is = item.getInputStream(); 75                     //得到文件保存的名称 76                     fileName = mkFileName(fileName); 77                     //得到文件保存的路径 78                     String savePathStr = mkFilePath(savePath, fileName); 79                     System.out.println("保存路径为:"+savePathStr); 80                     //创建一个文件输出流 81                     FileOutputStream fos = new FileOutputStream(savePathStr+File.separator+fileName); 82                     //创建一个缓冲区 83                     byte buffer[] = new byte[1024]; 84                     //判断输入流中的数据是否已经读完的标识 85                     int length = 0; 86                     //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据 87                     while((length = is.read(buffer))>0){ 88                         //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中 89                         fos.write(buffer, 0, length); 90                     } 91                     //关闭输入流 92                     is.close(); 93                     //关闭输出流 94                     fos.close(); 95                     //删除处理文件上传时生成的临时文件 96                     item.delete(); 97                     message = "文件上传成功"; 98                 } 99             }100         } catch (FileUploadBase.FileSizeLimitExceededException e) {101             e.printStackTrace();102             request.setAttribute("message", "单个文件超出最大值!!!");103             request.getRequestDispatcher("/message.jsp").forward(request, response);104             return;105         }catch (FileUploadBase.SizeLimitExceededException e) {106             e.printStackTrace();107             request.setAttribute("message", "上传文件的总的大小超出限制的最大值!!!");108             request.getRequestDispatcher("/message.jsp").forward(request, response);109             return;110         }catch (FileUploadException e) {111             // TODO Auto-generated catch block112             e.printStackTrace();113             message = "文件上传失败";114         }115         request.setAttribute("message",message);116         request.getRequestDispatcher("/message.jsp").forward(request, response);117     }118 119     @Override120     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {121         doGet(request, response);122     }123     //生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称124     public String mkFileName(String fileName){125         return UUID.randomUUID().toString()+"_"+fileName;126     }127     public String mkFilePath(String savePath,String fileName){128         //得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址129         int hashcode = fileName.hashCode();130         int dir1 = hashcode&0xf;131         int dir2 = (hashcode&0xf0)>>4;132         //构造新的保存目录133         String dir = savePath + "\\" + dir1 + "\\" + dir2;134         //File既可以代表文件也可以代表目录135         File file = new File(dir);136         if(!file.exists()){137             file.mkdirs();138         }139         return dir;140     }141 }
复制代码

 

  5、如果在文件上传中IO流成为了系统的性能瓶颈,可以考虑使用NIO来提高性能。改进servlet代码如下:

复制代码
  1 public class UploadHandleServlet2 extends HttpServlet{  2   3     @Override  4     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  5         //得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全  6         String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");  7         //上传时生成的临时文件保存目录  8         String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");  9         File file = new File(tempPath); 10         if(!file.exists()&&!file.isDirectory()){ 11             System.out.println("目录或文件不存在!"); 12             file.mkdir(); 13         } 14         //消息提示 15         String message = ""; 16         try { 17             //使用Apache文件上传组件处理文件上传步骤: 18             //1、创建一个DiskFileItemFactory工厂 19             DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory(); 20             //设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。 21             diskFileItemFactory.setSizeThreshold(1024*100); 22             //设置上传时生成的临时文件的保存目录 23             diskFileItemFactory.setRepository(file); 24             //2、创建一个文件上传解析器 25             ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory); 26             //解决上传文件名的中文乱码 27             fileUpload.setHeaderEncoding("UTF-8"); 28             //监听文件上传进度 29             fileUpload.setProgressListener(new ProgressListener(){ 30                 public void update(long pBytesRead, long pContentLength, int arg2) { 31                     System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead); 32                 } 33             }); 34             //3、判断提交上来的数据是否是上传表单的数据 35             if(!fileUpload.isMultipartContent(request)){ 36                 //按照传统方式获取数据 37                 return; 38             } 39             //设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB 40             fileUpload.setFileSizeMax(1024*1024); 41             //设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB 42             fileUpload.setSizeMax(1024*1024*10); 43             //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项 44             List<FileItem> list = fileUpload.parseRequest(request); 45             for (FileItem item : list) { 46                 //如果fileitem中封装的是普通输入项的数据 47                 if(item.isFormField()){ 48                     String name = item.getFieldName(); 49                     //解决普通输入项的数据的中文乱码问题 50                     String value = item.getString("UTF-8"); 51                     String value1 = new String(name.getBytes("iso8859-1"),"UTF-8"); 52                     System.out.println(name+"  "+value); 53                     System.out.println(name+"  "+value1); 54                 }else{ 55                     //如果fileitem中封装的是上传文件,得到上传的文件名称, 56                     String fileName = item.getName(); 57                     System.out.println(fileName); 58                     if(fileName==null||fileName.trim().equals("")){ 59                         continue; 60                     } 61                     //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt 62                     //处理获取到的上传文件的文件名的路径部分,只保留文件名部分 63                     fileName = fileName.substring(fileName.lastIndexOf(File.separator)+1); 64                     //得到上传文件的扩展名 65                     String fileExtName = fileName.substring(fileName.lastIndexOf(".")+1); 66                     if("zip".equals(fileExtName)||"rar".equals(fileExtName)||"tar".equals(fileExtName)||"jar".equals(fileExtName)){ 67                         request.setAttribute("message", "上传文件的类型不符合!!!"); 68                         request.getRequestDispatcher("/message.jsp").forward(request, response); 69                         return; 70                     } 71                     //如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法 72                     System.out.println("上传文件的扩展名为:"+fileExtName); 73                     //获取item中的上传文件的输入流 74                     InputStream fis = item.getInputStream(); 75                     //得到文件保存的名称 76                     fileName = mkFileName(fileName); 77                     //得到文件保存的路径 78                     String savePathStr = mkFilePath(savePath, fileName); 79                     System.out.println("保存路径为:"+savePathStr); 80                     //创建一个文件输出流 81                     FileOutputStream fos = new FileOutputStream(savePathStr+File.separator+fileName); 82                     //获取读通道 83                     FileChannel readChannel = ((FileInputStream)fis).getChannel(); 84                     //获取读通道 85                     FileChannel writeChannel = fos.getChannel(); 86                     //创建一个缓冲区 87                     ByteBuffer buffer = ByteBuffer.allocate(1024); 88                     //判断输入流中的数据是否已经读完的标识 89                     int length = 0; 90                     //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据 91                     while(true){ 92                         buffer.clear(); 93                         int len = readChannel.read(buffer);//读入数据 94                         if(len < 0){ 95                             break;//读取完毕  96                         } 97                         buffer.flip(); 98                         writeChannel.write(buffer);//写入数据 99                     }100                     //关闭输入流101                     fis.close();102                     //关闭输出流103                     fos.close();104                     //删除处理文件上传时生成的临时文件105                     item.delete();106                     message = "文件上传成功";107                 }108             }109         } catch (FileUploadBase.FileSizeLimitExceededException e) {110             e.printStackTrace();111             request.setAttribute("message", "单个文件超出最大值!!!");112             request.getRequestDispatcher("/message.jsp").forward(request, response);113             return;114         }catch (FileUploadBase.SizeLimitExceededException e) {115             e.printStackTrace();116             request.setAttribute("message", "上传文件的总的大小超出限制的最大值!!!");117             request.getRequestDispatcher("/message.jsp").forward(request, response);118             return;119         }catch (FileUploadException e) {120             // TODO Auto-generated catch block121             e.printStackTrace();122             message = "文件上传失败";123         }124         request.setAttribute("message",message);125         request.getRequestDispatcher("/message.jsp").forward(request, response);126     }127 128     @Override129     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {130         doGet(request, response);131     }132     //生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称133     public String mkFileName(String fileName){134         return UUID.randomUUID().toString()+"_"+fileName;135     }136     public String mkFilePath(String savePath,String fileName){137         //得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址138         int hashcode = fileName.hashCode();139         int dir1 = hashcode&0xf;140         int dir2 = (hashcode&0xf0)>>4;141         //构造新的保存目录142         String dir = savePath + "\\" + dir1 + "\\" + dir2;143         //File既可以代表文件也可以代表目录144         File file = new File(dir);145         if(!file.exists()){146             file.mkdirs();147         }148         return dir;149     }150 }
复制代码
  • 文件下载

  1、列出提供下载的文件资源

  要将Web应用系统中的文件资源提供给用户进行下载,首先我们要有一个页面列出上传文件目录下的所有文件,当用户点击文件下载超链接时就进行下载操作,编写一个ListFileServlet,用于列出Web应用系统中所有下载文件。

  ListFileServlet代码如下:

 

复制代码
 1 public class ListFileServlet extends HttpServlet{ 2     @Override 3     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 4         doPost(request, response); 5     } 6     @Override 7     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 8         // TODO Auto-generated method stub 9         //获取上传文件的目录10         String uploadFilePath = this.getServletContext().getRealPath("/WEB-INF/upload");11         //存储要下载的文件名12         Map<String, String> fileMap = new HashMap<String, String>();13         //递归遍历filepath目录下的所有文件和目录,将文件的文件名存储到map集合中14         fileList(new File(uploadFilePath),fileMap);15         //将Map集合发送到listfile.jsp页面进行显示16         request.setAttribute("fileMap", fileMap);17         request.getRequestDispatcher("/listfile.jsp").forward(request, response);18 19     }20     //递归遍历指定目录下的所有文件21     public void fileList(File file,Map fileMap){22         //如果file代表的不是一个文件,而是一个目录23         if(!file.isFile()){24             //列出该目录下的所有文件和目录25             File[] files = file.listFiles();26             //遍历files[]数组27             for (File file2 : files) {28                 System.out.println(file2.getName());29                 //递归30                 fileList(file2, fileMap);31             }32         }else{33               /* 处理文件名,上传后的文件是以uuid_文件名的形式去重新命名的,去除文件名的uuid_部分34                  file.getName().indexOf("_")检索字符串中第一次出现"_"字符的位置,如果文件名类似于:9349249849-88343-8344_阿_凡_达.avi35                   那么file.getName().substring(file.getName().indexOf("_")+1)处理之后就可以得到阿_凡_达.avi部分36               */37             String realName = file.getName().substring(file.getName().lastIndexOf("_")+1);38             //file.getName()得到的是文件的原始名称,这个名称是唯一的,因此可以作为key,realName是处理过后的名称,有可能会重复39             fileMap.put(file.getName(), realName);40         }41     }42 }
复制代码

 

  说明一下,一般文件路径在数据库中保存,然后再数据库中查询结果在页面显示。

  listfile.jsp页面

 

复制代码
 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2  <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 3  <!DOCTYPE HTML> 4  <html> 5    <head> 6      <title>下载文件显示页面</title> 7   </head> 8     9    <body>10       <!-- 遍历Map集合 -->11      <c:forEach var="me" items="${fileMap}">12          <c:url value="/servlet/downLoadServlet" var="downurl">13              <c:param name="filename" value="${me.key}"></c:param>14          </c:url>15          ${me.value}<a href="${downurl}">下载</a>16          <br/>17      </c:forEach>18    </body>19  </html>
复制代码

 

  2、文件下载

  DownLoadServlet的代码如下:

 

复制代码
 1 public class DownLoadServlet extends HttpServlet{ 2  3     @Override 4     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 5         //得到要下载的文件名 6         String fileName = request.getParameter("filename"); 7         fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8"); 8         //上传的文件都是保存在/WEB-INF/upload目录下的子目录当中 9         String fileSaveRootPath=this.getServletContext().getRealPath("/WEB-INF/upload");10         //        处理文件名11          String realname = fileName.substring(fileName.indexOf("_")+1);12         //通过文件名找出文件的所在目录13         String path = findFileSavePathByFileName(fileName,fileSaveRootPath);14         //得到要下载的文件15         File file = new File(path+File.separator+fileName);16         //如果文件不存在17         if(!file.exists()){18             request.setAttribute("message", "您要下载的资源已被删除!!");19             request.getRequestDispatcher("/message.jsp").forward(request, response);20             return;21         }22         23          //设置响应头,控制浏览器下载该文件24          response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));25          //读取要下载的文件,保存到文件输入流26          FileInputStream fis = new FileInputStream(path + File.separator + fileName);27          //创建输出流28          OutputStream fos = response.getOutputStream();29          //设置缓存区30          ByteBuffer buffer = ByteBuffer.allocate(1024);31          //输入通道32          FileChannel readChannel = fis.getChannel();33          //输出通道34          FileChannel writeChannel = ((FileOutputStream)fos).getChannel();35          while(true){36              buffer.clear();37              int len = readChannel.read(buffer);//读入数据38              if(len < 0){39                  break;//传输结束40              }41              buffer.flip();42              writeChannel.write(buffer);//写入数据43          }44          //关闭输入流45          fis.close();46          //关闭输出流47          fos.close();48     }49     50     @Override51     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {52         doPost(request, response);53     }54     //通过文件名和存储上传文件根目录找出要下载的文件的所在路径55     public String findFileSavePathByFileName(String fileName,String fileSaveRootPath){56         int hashcode = fileName.hashCode();57         int dir1 = hashcode&0xf;58         int dir2 = (hashcode&0xf0)>>4;59         String dir = fileSaveRootPath + "\\" + dir1 + "\\" + dir2;60         File file = new File(dir);61         if(!file.exists()){62             file.mkdirs();63         }64         return dir;65     }66 }
复制代码

 

  3、如果IO成为系统的瓶颈,可以考虑使用NIO来实现下载,提供系统性能,改进后的DownloadServlet代码如下:

复制代码
 1 public class DownLoadServlet1 extends HttpServlet{ 2  3     @Override 4     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 5         //得到要下载的文件名 6         String fileName = request.getParameter("filename"); 7         fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8"); 8         //上传的文件都是保存在/WEB-INF/upload目录下的子目录当中 9         String fileSaveRootPath=this.getServletContext().getRealPath("/WEB-INF/upload");10         //        处理文件名11          String realname = fileName.substring(fileName.indexOf("_")+1);12         //通过文件名找出文件的所在目录13         String path = findFileSavePathByFileName(fileName,fileSaveRootPath);14         //得到要下载的文件15         File file = new File(path+File.separator+fileName);16         //如果文件不存在17         if(!file.exists()){18             request.setAttribute("message", "您要下载的资源已被删除!!");19             request.getRequestDispatcher("/message.jsp").forward(request, response);20             return;21         }22         23          //设置响应头,控制浏览器下载该文件24          response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));25          //读取要下载的文件,保存到文件输入流26          FileInputStream in = new FileInputStream(path + File.separator + fileName);27          //创建输出流28          OutputStream os = response.getOutputStream();29          //设置缓存区30          byte[] bytes = new byte[1024];31          int len = 0;32          while((len = in.read(bytes))>0){33              os.write(bytes);34          }35          //关闭输入流36          in.close();37          //关闭输出流38          os.close();39     }40     41     @Override42     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {43         doPost(request, response);44     }45     //通过文件名和存储上传文件根目录找出要下载的文件的所在路径46     public String findFileSavePathByFileName(String fileName,String fileSaveRootPath){47         int hashcode = fileName.hashCode();48         int dir1 = hashcode&0xf;49         int dir2 = (hashcode&0xf0)>>4;50         String dir = fileSaveRootPath + "\\" + dir1 + "\\" + dir2;51         File file = new File(dir);52         if(!file.exists()){53             file.mkdirs();54         }55         return dir;56     }57 }
原创粉丝点击