• 10.Java文件传输


    一.文件上传和下载

    1.准备工作

    • 搭建maven-archetype-webapp项目,导入jar包

     1 <dependencies>
     2     <dependency>
     3         <groupId>commons-io</groupId>
     4         <artifactId>commons-io</artifactId>
     5         <version>2.6</version>
     6     </dependency>
     7 
     8     <dependency>
     9         <groupId>commons-fileupload</groupId>
    10         <artifactId>commons-fileupload</artifactId>
    11         <version>1.4</version>
    12     </dependency>
    13 
    14 </dependencies>

    2.注意事项

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

    2. 为防止文件覆盖现象发生,要为上传文件产生一个唯一的文件名。(使用UUID,md5,位运算算法)

    3. 要限制上传文件的最大值

    4. 可以限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法

    3.需要用到的类详解

      ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象,在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象。所以,我们需要在进行解析工作前构造好DisFileItemFactory对象,通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性。

    (1)FileItem类

    在HTML页面input必须有name  <input type="file" name="file1"> 

    表单中如果包含一个文件上传输入项的话,这个表单的enctype属性就必须设置为multipart/form-data

     1 <%--
     2 通过表单上传文件
     3     get:上传文件大小有限制
     4     post:上传文件大小无限制
     5 
     6 ${pageContext.request.contextPath}获取服务器路径
     7 --%>
     8 <form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
     9     上传用户:<input type="text" name="username"> <br>
    10     <p><input type="file" name="file1"></p>
    11     <p><input type="file" name="file1"></p>
    12     <p><input type="submit" value="提交"> | <input type="reset" value="重置">  </p>
    13 </form>

    注意:表单提交方式为post不限制上传大小,表单类型: enctype="multipart/form-data" 

    (2)常用方法:

    4.ServletFileUpload类

    ServletFileUpload负责处理上传的数据,并将表单中每个输入项封装成一个FileItem对象中,使用其parseRequest(HttpServletRequest)方法可以讲通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回。使用该方法处理上传文件简单易用。

    5.文件上传程序:

    index.jsp:

     1 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
     2 <html>
     3 <head>
     4     <title>index</title>
     5 </head>
     6 <body>
     7 
     8 <%--
     9 通过表单上传文件
    10     get:上传文件大小有限制
    11     post:上传文件大小无限制
    12 
    13 ${pageContext.request.contextPath}获取服务器路径
    14 --%>
    15 <form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
    16     上传用户:<input type="text" name="username"> <br>
    17     <p><input type="file" name="file1"></p>
    18     <p><input type="file" name="file1"></p>
    19     <p><input type="submit" value="提交"> | <input type="reset" value="重置">  </p>
    20 </form>
    21 
    22 
    23 </body>
    24 </html>

    FileServlet.java:

      1 import org.apache.commons.fileupload.FileItem;
      2 import org.apache.commons.fileupload.FileUploadException;
      3 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
      4 import org.apache.commons.fileupload.servlet.ServletFileUpload;
      5 
      6 import javax.servlet.ServletException;
      7 import javax.servlet.http.HttpServlet;
      8 import javax.servlet.http.HttpServletRequest;
      9 import javax.servlet.http.HttpServletResponse;
     10 import java.io.*;
     11 import java.util.List;
     12 import java.util.UUID;
     13 
     14 public class FileServlet extends HttpServlet {
     15     @Override
     16     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     17 
     18 
     19         //判断上传的文件是普通表单还是带文件的表单
     20         if (!ServletFileUpload.isMultipartContent(req)) {
     21             return; //普通表单直接返回
     22         }
     23 
     24         //创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件
     25         String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
     26         File uploadFile = new File(uploadPath);
     27         if (!uploadFile.exists()) {
     28             uploadFile.mkdir(); //没有目录创建目录
     29         }
     30 
     31         //缓存,临时文件
     32         //临时路径,加入文件超过了预期的大小,我们就把它放在一个临时文件中,过几天自动删除,或者提醒用户转存为永久
     33         String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
     34         File tmpFile = new File(tmpPath);
     35         if (!tmpFile.exists()) {
     36             tmpFile.mkdir(); //没有临时目录创建目录
     37         }
     38 
     39         //处理上传文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦
     40         //但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,它依赖于common-io组件
     41         try {
     42             //1.创建DiskFileItemFactory对象,设置文件上传路径和文件大小限制
     43             DiskFileItemFactory factory = getDiskFileItemFactory(tmpFile);
     44 
     45             //2.获取ServletFileUpload
     46             ServletFileUpload upload = getServletFileUpload(factory);
     47 
     48             //3.处理上传文件
     49             String msg = uploadParseRequest(upload, req, uploadPath);
     50 
     51             //Servlet请求转发消息
     52             req.setAttribute("msg", msg);
     53             req.getRequestDispatcher("info.jsp").forward(req, resp);
     54 
     55         } catch (FileUploadException e) {
     56             e.printStackTrace();
     57         }
     58 
     59     }
     60 
     61     public static DiskFileItemFactory getDiskFileItemFactory(File file) {
     62         DiskFileItemFactory factory = new DiskFileItemFactory();
     63         //通过这个工厂设置一个缓存区,当上传的文件大于这个缓冲区的时候,将它放到临时文件中
     64         factory.setSizeThreshold(1024 * 1024);  //设置缓冲区大小1M
     65         factory.setRepository(file);            //设置临时文件目录
     66         return factory;
     67     }
     68 
     69     public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
     70         ServletFileUpload upload = new ServletFileUpload(factory);
     71 
     72         //监听文件上传的进度
     73         //pBytesRead:已经读取到的文件大小
     74         //pContentLength:文件大小
     75         upload.setProgressListener((pBytesRead, pContentLength, pItems) -> System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead));
     76 
     77         //处理乱码问题
     78         upload.setHeaderEncoding("UTF-8");
     79 
     80         //设置单个文件的最大值 10M
     81         upload.setFileSizeMax(1024 * 1024 * 10);
     82 
     83         //设置总共能够上传文件的大小 10M
     84         upload.setSizeMax(1024 * 1024 * 10);
     85 
     86         return upload;
     87     }
     88 
     89     public static String uploadParseRequest(ServletFileUpload upload, HttpServletRequest req, String uploadPath) throws FileUploadException {
     90 
     91         String msg = new String();
     92 
     93         try {
     94             //把前端请求解析,封装成一个FileItem对象,需要从ServletFileUpload对象中获取
     95             List<FileItem> fileItems = upload.parseRequest(req);
     96 
     97             //处理每一个表单对象
     98             for (FileItem fileItem : fileItems) {
     99                 //判断上传的文件是普通的表单还是带文件的表单
    100                 if (fileItem.isFormField()) {
    101                     //普通表单
    102                     //getFileName指的是前端表单控件的name
    103                     String name = fileItem.getFieldName();
    104                     String value = fileItem.getString("UTF-8");
    105                     System.out.println(name + ":" + value);
    106                 } else {
    107                     //文件
    108                     //1.处理文件
    109                     String uploadFileName = fileItem.getName();
    110                     //处理文件名不合法的情况
    111                     if (uploadFileName.trim().equals("") || uploadFileName == null) {
    112                         continue;
    113                     }
    114                     //获得上传文件名 /images/girl/paojie.png
    115                     String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
    116                     //获得文件后缀名
    117                     String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
    118                     /*
    119                         如果文件后缀名fileExtName 不是我们所需要的就直接return不处理,并告诉用户文件类型不正确
    120                     */
    121 
    122                     System.out.println("文件信息 [文件名:" + fileName + "---文件类型:" + fileExtName + "]");
    123 
    124                     //可以使用UUID来保证文件名唯一
    125                     //UUID.randomUUID(),随机生成一个唯一识别的通用码:
    126                     String uuidPath = UUID.randomUUID().toString();
    127 
    128                     //对于我们创建的pojo实体类,如果想要在多台电脑上运行在网络上传输都要实现序列化接口
    129                     //implement Serializable
    130 
    131                     //2.存放地址
    132                     //生成文件真实存放地址
    133                     String realPath = uploadPath + "/" + uuidPath;
    134                     //给每一个文件创建一个文件夹
    135                     File realPathFile = new File(realPath);
    136                     if (!realPathFile.exists()) {
    137                         realPathFile.mkdir();
    138                     }
    139 
    140                     //3.文件传输
    141                     //获得文件上传流
    142                     InputStream inputStream = fileItem.getInputStream();
    143 
    144                     //创建一个文件输出流
    145                     FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
    146 
    147                     //创建一个缓冲区
    148                     byte[] buffer = new byte[1024 * 1024];
    149 
    150                     //判断是否读取完毕
    151                     int len = 0;
    152                     //如果大于0说明还存在数据
    153                     while ((len = inputStream.read(buffer)) > 0) {
    154                         fos.write(buffer, 0, len);
    155                     }
    156 
    157                     //关闭流
    158                     fos.close();
    159                     inputStream.close();
    160 
    161                     msg = "文件上传成功!";
    162                     fileItem.delete();//上传成功,清除临时文件
    163                 }
    164             }
    165         } catch (IOException e) {
    166             e.printStackTrace();
    167         }
    168 
    169         return msg;
    170     }
    171 }

    web.xml注册:

     1 <!--注册Servlet-->
     2 <servlet>
     3   <servlet-name>FileServlet</servlet-name>
     4   <servlet-class>wzh.servlet.FileServlet</servlet-class>
     5 </servlet>
     6 
     7 <!--Servlet的请求路径-->
     8 <servlet-mapping>
     9   <servlet-name>FileServlet</servlet-name>
    10   <url-pattern>/upload.do</url-pattern>
    11 </servlet-mapping>

    info.jsp:

     1 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
     2 <html>
     3 <head>
     4     <title>info</title>
     5 </head>
     6 <body>
     7 
     8 ${msg}
     9 </body>
    10 </html>

    上传成功后保存路径:里面有tmp和upload目录

    6.总结

    主要理解思路和流程,其次才是调用的api和代码

  • 相关阅读:
    jQuery Easing 动画效果扩展--使用Easing插件,让你的动画更具美感。
    JavaScript表达式--掌握最全的表达式,一切尽在掌握中,让表达不再是难事
    JavaScript的格式--从格式做起,做最严谨的工程师
    JavaScript 简介--对javascript的初识,最基础的了解
    手机web页面制作时的注意事项
    实现像淘宝一样牛的语音搜索框
    Cufon在渲染网页字体你不知道的事
    .net中单选按钮RadioButton,RadioButtonList 以及纯Html中radio的用法实例?
    使用C#把发表的时间改为几个月,几天前,几小时前,几分钟前,或几秒前
    eval解析JSON中的注意点
  • 原文地址:https://www.cnblogs.com/zhihaospace/p/12317721.html
Copyright © 2020-2023  润新知