• common-fileupload组件实现java文件上传和下载


    简介:文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到本地。对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件。这个common-fileupload上传组件的jar包可以去apache官网上面下载,也可以在struts的lib文件夹下面找到,struts上传的功能就是基于这个实现的。common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。

    文件上传

    (1)文件上传前端界面(fileupload.jsp)

     1 <%@ page language="java" contentType="text/html; charset=UTF-8"
     2     pageEncoding="UTF-8"%>
     3 <!DOCTYPE html>
     4 <html>
     5 <head>
     6 <meta charset="UTF-8">
     7 <title>文件上传</title>
     8 </head>
     9 <body>
    10 <form action="FileUpload" method="post" enctype="multipart/form-data">
    11     <p><label>用户名:<input type="text" name="username"></label></p>
    12     <p><label>&nbsp;&nbsp;&nbsp;&nbsp;码:<input type="password" name="pwd"></label></p>
    13     <p><input type="file" name="upfile"></p>
    14     <input type="submit" value="提交">
    15 </form> 
    16 </body>
    17 </html>

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

    (2)文件上传细节

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

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

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

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

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

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

    (3)处理文件上传的servlet

      1 package com.etc.utils;
      2 
      3 import java.io.File;
      4 import java.io.IOException;
      5 import java.io.PrintWriter;
      6 import java.util.List;
      7 import java.util.UUID;
      8 
      9 import javax.servlet.ServletException;
     10 import javax.servlet.annotation.WebServlet;
     11 import javax.servlet.http.HttpServlet;
     12 import javax.servlet.http.HttpServletRequest;
     13 import javax.servlet.http.HttpServletResponse;
     14 
     15 import org.apache.commons.fileupload.FileItem;
     16 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
     17 import org.apache.commons.fileupload.servlet.ServletFileUpload;
     18 
     19 @WebServlet("/FileUpload")
     20 public class FileUpload extends HttpServlet {
     21     private static final long serialVersionUID = 1L;
     22 
     23     public FileUpload() {
     24         super();
     25     }
     26 
     27     protected void doGet(HttpServletRequest request, HttpServletResponse response)
     28             throws ServletException, IOException {
     29         request.setCharacterEncoding("UTF-8");
     30         response.setCharacterEncoding("UTF-8");
     31         response.setContentType("text/html;charset=UTF-8");
     32         PrintWriter out = response.getWriter();
     33         String filedName = "";
     34 
     35         // 1、创建工厂类:DiskFileItemFactory factory=new DiskFileItemFactory();
     36         DiskFileItemFactory factory = new DiskFileItemFactory();
     37         // 2、创建解析器:ServletFileUpload upload=new ServletFileUpload(factory);
     38         ServletFileUpload upload = new ServletFileUpload(factory);
     39         upload.setHeaderEncoding("UTF-8");
     40 
     41         // 设置缓冲区大小与临时文件目录
     42         factory.setSizeThreshold(1024 * 1024 * 10);
     43         File fileDir = new File("e:\upload");
     44         if (!fileDir.exists())
     45             fileDir.mkdirs();
     46         // 设置文件存储仓库
     47         factory.setRepository(fileDir);
     48         // 设置单个文件大小限制
     49         upload.setFileSizeMax(1024 * 1024 * 10);
     50         // 设置所有文件总和大小限制
     51         upload.setSizeMax(1024 * 1024 * 100);
     52 
     53         // 3、使用解析器解析request对象:List<FileItem> list=upload.parseRequest(request);
     54         /**
     55          * FileItem
     56          * String getFieldName():获取表单项的name的属性值。
     57          * String getName():获取文件字段的文件名。如果是普通字段,则返回null
     58          * String getString():获取字段的内容。如果是普通字段,则是它的value值;如果是文件字段,则是文件内容。 
     59          * String getContentType():获取上传的文件类型,例如text/plain、image。如果是普通字段,则返回null。 
     60          * long getSize():获取字段内容的大小,单位是字节。 
     61          * boolean isFormField():判断是否是普通表单字段,若是,返回true,否则返回false。
     62          * InputStream getInputStream():获得文件内容的输入流。如果是普通字段,则返回value值的输入流
     63          */
     64         try {
     65             List<FileItem> list = upload.parseRequest(request);
     66             System.out.println(list);
     67             for (FileItem fileItem : list) {
     68                 /*
     69                  * 对文件进行处理
     70                  */
     71                 if (!fileItem.isFormField() && fileItem.getName() != null && !"".equals(fileItem.getName())) {
     72                     String fileName = fileItem.getName();
     73                     String uuid = UUID.randomUUID().toString();
     74                     //获取文件的后缀名
     75                     //String suffix = fileName.substring(fileName.lastIndexOf("."));
     76                     //获取文件上传目录路径,在项目部署路径下的upload目录里。若想让浏览器不能直接访问到图片,可以放在WEB-INF下
     77                     String uploadPath = request.getSession().getServletContext().getRealPath("/upload");
     78                     File file = new File(uploadPath);
     79                     file.mkdirs();
     80                     //将文件写入对应路径,并对文件进行重命名
     81                     fileItem.write(new File(uploadPath, uuid + "_"+ fileName));
     82                 }
     83                 /*
     84                  * 对表中的普通字段进行处理
     85                  */
     86                 if(fileItem.isFormField()) {
     87                     filedName = fileItem.getFieldName();
     88                     String username = null;
     89                     String pwd = null;
     90                     if("username".equals(filedName)) {
     91                         username = fileItem.getString("UTF-8");
     92                         out.println("用户名:" + username);
     93                     }
     94                     if("pwd".equals(filedName)) {
     95                         pwd = fileItem.getString("UTF-8");
     96                         out.println("	密码:" + pwd);
     97                     }
     98                 }
     99             }
    100         } catch (Exception e) {
    101             // TODO Auto-generated catch block
    102             e.printStackTrace();
    103         }
    104 
    105     }
    106     protected void doPost(HttpServletRequest request, HttpServletResponse response)
    107             throws ServletException, IOException {
    108         doGet(request, response);
    109     }
    110 }

    文件下载

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

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

     1 package com.etc.utils;
     2 
     3 import java.io.File;
     4 import java.io.IOException;
     5 import java.util.HashMap;
     6 import java.util.Map;
     7 
     8 import javax.servlet.ServletException;
     9 import javax.servlet.annotation.WebServlet;
    10 import javax.servlet.http.HttpServlet;
    11 import javax.servlet.http.HttpServletRequest;
    12 import javax.servlet.http.HttpServletResponse;
    13 
    14 @WebServlet("/FileDownLoad")
    15 public class FileDownLoad extends HttpServlet {
    16     private static final long serialVersionUID = 1L;
    17     public FileDownLoad() {
    18         super();
    19     }
    20     
    21     protected void doGet(HttpServletRequest request, HttpServletResponse response)
    22             throws ServletException, IOException {
    23         response.getWriter().append("Served at: ").append(request.getContextPath());
    24         // 获取上传文件的目录
    25         String uploadFilePath = this.getServletContext().getRealPath("/upload");
    26         // 储存要下载的文件名
    27         Map<String, String> fileMap = new HashMap<String, String>();
    28         // 递归遍历fileMap目录下的所有文件和目录,将文件储存到map集合中
    29         fileList(new File(uploadFilePath),fileMap);
    30         //将Map集合发送到listfile.jsp页面进行显示
    31         request.setAttribute("fileMap", fileMap);
    32         request.getRequestDispatcher("/listfile.jsp").forward(request, response);
    33     }
    34 
    35     public void fileList(File file, Map<String,String> fileMap) {
    36         // 如果file代表的不是一个文件而是一个目录
    37         if (!file.isFile()) {
    38             File[] files = file.listFiles();
    39             for (File file2 : files) {
    40                 fileList(file2, fileMap);
    41             }
    42         } else {
    43             /**
    44              * 处理文件名,上传后的文件是以uuid_文件名的形式去重新命名的,去除文件名的uuid_部分
    45              * file.getName().indexOf("_")检索字符串中第一次出现"_"字符的位置,如果文件名类似于:9349249849-88343-8344_timer.avi
    46              * 那么file.getName().substring(file.getName().indexOf("_")+1)处理之后就可以得到timer.avi部分
    47              */
    48             String realName = file.getName().substring(file.getName().lastIndexOf("_")+1);
    49             System.out.println(realName);
    50             fileMap.put(file.getName(), realName);
    51         }
    52     }
    53 
    54     protected void doPost(HttpServletRequest request, HttpServletResponse response)
    55             throws ServletException, IOException {
    56         doGet(request, response);
    57     }
    58 }

    (2)创建显示文件列表的jsp界面(listfile.jsp)

     1 <%@ page language="java" contentType="text/html; charset=UTF-8"
     2     pageEncoding="UTF-8"%>
     3 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
     4 <!DOCTYPE html>
     5 <html>
     6 <head>
     7 <meta charset="UTF-8">
     8 <link href="css/bootstrap.css" rel="stylesheet">
     9 <title>下载文件显示界面</title>
    10 </head>
    11 <body>
    12     <div class="container">
    13         <table class="table table-bordered">
    14             <caption>文件下载列表</caption>
    15             <c:forEach var="me" items="${requestScope.fileMap}">
    16                 <tr>
    17                     <c:url value="DownLoadServlet" var="downurl">
    18                         <c:param name="filename" value="${me.key}"></c:param>
    19                     </c:url>
    20                 
    21                     <td>${me.value}</td><td><a href="${downurl}">下载</a></td>
    22                 </tr>
    23             </c:forEach>
    24         </table>
    25     </div>
    26 </body>
    27 </html>

    (3)实现文件下载的servlet

    DownLoadServlet的代码如下:

     1 package com.etc.utils;
     2 
     3 import java.io.File;
     4 import java.io.FileInputStream;
     5 import java.io.IOException;
     6 import java.io.InputStream;
     7 import java.io.OutputStream;
     8 import java.net.URLEncoder;
     9 
    10 import javax.servlet.ServletException;
    11 import javax.servlet.annotation.WebServlet;
    12 import javax.servlet.http.HttpServlet;
    13 import javax.servlet.http.HttpServletRequest;
    14 import javax.servlet.http.HttpServletResponse;
    15 
    16 import org.apache.commons.io.IOUtils;
    17 
    18 @WebServlet("/DownLoadServlet")
    19 public class DownLoadServlet extends HttpServlet {
    20     private static final long serialVersionUID = 1L;
    21     
    22     public DownLoadServlet() {
    23         super();
    24         // TODO Auto-generated constructor stub
    25     }
    26 
    27     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    28         String fileName = request.getParameter("filename");
    29         //获取文件路径
    30         String fileSaveRootPath = this.getServletContext().getRealPath("/upload");
    31         //获取真实的文件名
    32         String realname = fileName.substring(fileName.indexOf("_")+1);
    33         //得到要下载的文件
    34         File file = new File(fileSaveRootPath+File.separator+fileName);
    35         //如果文件不存在
    36         if(!file.exists()) {
    37             request.setAttribute("msg", "您要下载的文件已被删除!");
    38             request.getRequestDispatcher("/message.jsp").forward(request, response);
    39             return;
    40         }
    41         //设置响应头,控制浏览器下载该文件 可通过URLEncoder.encode(realname, "UTF-8")实现对下载的文件进行重命名
    42         response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
    43         //获取输入输出流
    44         InputStream is = new FileInputStream(file);
    45         OutputStream os = response.getOutputStream();
    46         //调用common-io下面的静态方法,用于实现文件复制(从服务器端复制到本地)
    47         IOUtils.copy(is, os);
    48         is.close();
    49     }
    50 
    51     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    52         doGet(request, response);
    53     }
    54 }

    文件上传下载还能进行很多优化,可参考博文

  • 相关阅读:
    DBLE快速开始
    RPM包直接安装MySQL
    初试DTLE-单向-聚合-分散复制
    使用 TiUP cluster 在单机上安装TiDB
    如何升级到MySQL8.0
    SpringBoot集成AOP操作日志
    IDEA常用插件
    JAVA中如何实现字符串的反转?
    mysql数据库忘记密码时如何修改密码
    二分查找算法
  • 原文地址:https://www.cnblogs.com/remote/p/11038345.html
Copyright © 2020-2023  润新知