首页 > 其他分享 >文件上传功能

文件上传功能

时间:2024-05-09 17:25:01浏览次数:24  
标签:文件 功能 String void ServletFileUpload 上传 servletFileUpload

  1. 文件上传原理

    • 客户端请求:用户通过浏览器或应用程序选择要上传的文件,并发送 HTTP POST 请求到服务器。

    • 服务器接收:服务器接收到请求后,解析请求头和请求体,获取上传的文件数据。

    • 文件处理:服务器将文件数据存储在临时目录中,然后进行进一步的处理,如验证、重命名等。

    • 存储:最终,服务器将处理后的文件存储在指定目录,以便后续访问和使用。

  2. 文件上传实现方式

    在 Java 中,文件上传可以使用多种方法实现,最常见的有以下几种:

    • Servlet API:使用 Servlet API 提供的 HttpServletRequest 对象来处理文件上传。通常需要解析请求,获取文件流,然后保存文件。

    • Apache Commons FileUpload:这是一个开源的文件上传库,提供了更方便的文件上传功能,支持多文件上传、进度监控等。

    • Spring Framework:Spring 框架提供了 MultipartFile 接口,用于处理文件上传,它对文件上传进行了更高层次的封装。

  3. 注意事项

    • 为保证服务器安全,上传文件应当保存在外界无法直接访问的路径(如 WEB-INF 目录下)
    • 为防止文件覆盖,要为上传的文件生成一个唯一的文件名(如-时间戳,-uuid,-md5,-位运算算法)
    • 要限制上传文件的大小的最大值。
    • 可以限制上传文件的类型,在获取上传文件名时,判断后缀名是否合法。
  4. 上传案例类的介绍

    • 用到的jar包:

      commons-fileupload:Apache 的文件上传组件,取代原生的文件上传流。
      commons-io:commons-fileupload 组件依赖于该组件。

    • 前端表单:

      提交方式:method=“post”(post传送的数据量大,可视为不受限制)
      编码类型:enctype="multipart/form-data"(表单包含文件上传控件时必须使用)

    • 类的介绍:

      //* DiskFileItemFactory 
    
      // 1、设置临时文件夹
      void setRepository(File repository)
      // 2、设置文件缓存区大小
      void setSizeThreshold(int sizeThreshold)
    
      //*ServletFileUpload  
      // 1、静态方法:判断表单是否包含文件上传控件,负责处理文件数据
      static boolean isMultipartContent(HttpServletRequest request)
          
      // 2、父类方法:设置FileItemFactory属性,也可通过构造方法设置
      void setFileItemFactory(FileItemFactory factory)
         
      // 3、解析前端请求,将每个表单项解析并封装成FileItem对象,以List列表的形式返回。
      List<FileItem> parseRequest(HttpServletRequest request)
          
      //4、父类方法:监听文件上传进度
      void setProgressListener(ProgressListener pListener)
          
      //5、父类方法:处理乱码问题
      void setHeaderEncoding(String encoding)
          
      //6、父类方法:设置单个文件的最大值
      void setFileSizeMax(long fileSizeMax)
          
      //7、父类方法:设置总共能够上传的文件大小
      void setSizeMax(long sizeMax)
      //*DiskFileItem:FileItem 接口实现类
    
      // 1、判断表单项是否为上传文件:普通文本返回true,否则返回false
      boolean isFormField();
    
      // 2、获取字段名:表单项name属性的值
      String getFieldName();
    
      // 3、FileItem对象中保存的数据流内容:即表单项为普通文本的输入值
      String getString();
    
      // 4、获取表单项为文件上传的文件名
      String getName();
    
      // 5、获取上传文件的输入流
      InputStream getInputStream();
    
      // 6、清空FileItem类对象中存放的主体内容,如果主体内容被保存在临时文件中,delete方法将删除该临时文件
      void delete();
    
    
  5. 实现步骤

    • 判断表单:是否包含文件上传控件。
    • 创建上传文件和临时文件的保存路径。
    • 创建 DiskFileItemFactory 对象。
      • 设置临时文件夹
      • 设置缓冲区大小
    • 创建 ServletFileUpload 对象
      • 设置 FileItemFactory
      • 监听文件上传进度、处理乱码问题、设置单个文件和总共上传文件的最大值
    • 解析请求并处理文件传输
      • 解析前端请求,将每个表单项解析并封装成 FileItem 对象
      • 判断表单项是否为上传文件
      • 处理普通文本:
        • 获取字段名
        • 获取数据流内容
      • 处理文件:
        • 获取上传文件名
        • 生成随机 UUID 作为文件存储路径,并为其生成文件夹
        • 通过 IO 流传输文件
    <!--前端页面-->
    <form action="${pageContext.request.contextPath}/upload.do" method="post" enctype="multipart/form-data">
        <p>上传用户:<input type="text" name="username"></p>
        <p><input type="file" name="file"></p>
        <p>
            <input type="submit">|<input type="reset">
        </p>
    </form>
    
      public class FileServlet extends HttpServlet {
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
              // 判断表单是否包含文件上传控件
              if (!ServletFileUpload.isMultipartContent(req)) { // 不包含文件上传控件,即普通表单
                  return;
              }
    
              // 创建上传文件的保存路径:外界无法直接访问
              String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
              File uploadFile = new File(uploadPath);
              makeDirIfNotExist(uploadFile);
    
              // 创建临时文件的保存路径
              String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
              File tmpFile = new File(tmpPath);
              makeDirIfNotExist(tmpFile);
    
              // 1、创建DiskFileItemFactory对象
              DiskFileItemFactory factory = getDiskFileItemFactory(tmpFile);
              // 2、创建ServletFileUpload对象
              ServletFileUpload servletFileUpload = getServletFileUpload(factory);
              // 3、解析请求并处理文件传输
              String msg = "";
              try {
                  msg = uploadParseRequest(req, servletFileUpload, uploadPath);
              } catch (FileUploadException e) {
                  e.printStackTrace();
              }
    
              req.setAttribute("msg", msg);
              req.getRequestDispatcher("/success.jsp").forward(req, resp);
          }
    
    
          private String uploadParseRequest(HttpServletRequest httpServletRequest, ServletFileUpload servletFileUpload, String uploadPath)
                  throws FileUploadException, IOException {
              String msg = "";
    
              // 解析前端请求,将每个表单项解析并封装成FileItem对象
              List<FileItem> fileItems = servletFileUpload.parseRequest(httpServletRequest);
              for (FileItem fileItem : fileItems) {
                  // 判断表单项是否为上传文件
                  if (fileItem.isFormField()) { // 普通文本
                      String filedName = fileItem.getFieldName(); // 获取字段名:表单项name属性的值
                      String value = fileItem.getString("UTF-8"); // FileItem对象中保存的数据流内容:即表单项为普通文本的输入值
                      System.out.println(filedName + ":" + value);
                  } else { // 上传文件
                      // ------------------------1、处理文件------------------------
    
    
                      String uploadFileName = fileItem.getName();// 上传文件名
                      System.out.println("上传的文件名:" + uploadFileName);
    
                      if (uploadFileName == null || uploadFileName.trim().equals("")) { // 文件名为空值或空
                          continue; // 进入下一轮循环,判断下一个FileItem对象
                      }
    
                      String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1); // 文件后缀名
                      System.out.println("文件信息【文件名:" + uploadFileName + ",文件类型:" + fileExtName + "】");
    
                      // 使用UUID保证文件名唯一
                      String uuidPath = UUID.randomUUID().toString();
    
                      // ------------------------2、处理路径------------------------
    
                      // 存储路径:uploadPath
                      String realPath = uploadPath + '/' + uuidPath; // 真实存在的路径
                      // 给每个文件创建一个文件夹
                      File realPathFile = new File(realPath);
                      makeDirIfNotExist(realPathFile);
    
                      // ------------------------3、文件传输------------------------
    
                      // 获得输入流
                      InputStream is = fileItem.getInputStream();
                      // 获得输出流
                      FileOutputStream fos = new FileOutputStream(realPathFile + "/" + uploadFileName);
                      // 创建缓冲区
                      byte[] buffer = new byte[1024];
    
                      int len;
                      while ((len = is.read(buffer)) > 0) {
                          fos.write(buffer, 0, len);
                      }
                      msg = "文件上传成功!";
    
                      fileItem.delete(); // 上传成功,清除临时文件
    
                      fos.close();
                      is.close();
                  }
              }
    
              return msg;
          }
    
    
          private ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
              // ServletFileUpload servletFileUpload = new ServletFileUpload(factory); // 构造方法设置FileItemFactory
    
              ServletFileUpload servletFileUpload = new ServletFileUpload();
              servletFileUpload.setFileItemFactory(factory); // 设置FileItemFactory
    
              // ------------------------辅助功能------------------------
              // 监听文件上传进度
              servletFileUpload.setProgressListener(new ProgressListener() {
                  /**
                   *
                   * @param pBytesRead      已读取的文件大小
                   * @param pContentLength  文件大小
                   * @param pItems
                   */
                  @Override
                  public void update(long pBytesRead, long pContentLength, int pItems) {
                      String percentage = (int) (((double) pBytesRead / pContentLength) * 100) + "%";
                      System.out.println("总大小:" + pContentLength + ",已上传:" + pBytesRead + "\t" + percentage);
                  }
              });
              // 处理乱码问题
              servletFileUpload.setHeaderEncoding("UTF-8");
              // 设置单个上传文件的最大值
              servletFileUpload.setFileSizeMax(1024 * 1024 * 10); // 10M
              // 设置总共上传文件的最大值
              servletFileUpload.setSizeMax(1024 * 1024 * 10); // 10M
    
              return servletFileUpload;
          }
    
          /**
           * 获得磁盘文件项目工程,设置缓冲文件夹及缓冲区大小
           *
           * @param tmpFile 缓冲文件夹
           * @return
           */
          private DiskFileItemFactory getDiskFileItemFactory(File tmpFile) {
              // return new DiskFileItemFactory(1024 * 1024, tmpFile);
    
              DiskFileItemFactory factory = new DiskFileItemFactory();
    
              // ------------------------辅助功能------------------------
              factory.setSizeThreshold(1024 * 1024); // 1M(缓冲区大小):上传文件大于缓冲区大小时,fileupload组件将使用临时文件缓存上传文件
              factory.setRepository(tmpFile); // 临时文件夹
              return factory;
          }
    
          /**
           * 如果文件目录不存在,为其创建目录
           *
           * @param file
           */
          private void makeDirIfNotExist(File file) {
              if (!file.exists()) {
                  file.mkdir();
              }
          }
      }
    

标签:文件,功能,String,void,ServletFileUpload,上传,servletFileUpload
From: https://www.cnblogs.com/hytip/p/18182737

相关文章

  • 瞬回丝滑!30秒解决win11文件管理器卡顿问题!
    命令文本:regadd"HKCU\Software\Classes\CLSID\{d93ed569-3b3e-4bff-8355-3c44f6a52bb5}\InprocServer32"/f/ve如需取消输入这个命令regdelete"HKCU\Software\Classes\CLSID\{d93ed569-3b3e-4bff-8355-3c44f6a52bb5}"/f 联想笔记本运行缓慢?别担心,我们为您提供了两种简......
  • 向文件写入当前系统时间
    向文件写入当前系统时间/**********************************************************************filename:写入系统时间.c*author:[email protected]*date:2024年4月9日*function:......
  • 利用标准IO函数接口实现文件拷贝,把本地磁盘的文件A中的数据完整的拷贝到另一个文本B中
    利用标准IO函数接口实现文件拷贝,把本地磁盘的文件A中的数据完整的拷贝到另一个文本B中,如果文本B不存在则创建,要求文本A的名称和文本B的名称通过命令行传递,并进行验证是否正确。/******************************************************************** author :18312615416@1......
  • 国产linux系统(银河麒麟,统信uos)使用 PageOffice 国产版在线打开 word 文件
    PageOffice国产版:支持信创系统,支持银河麒麟V10和统信UOS,支持X86(intel、兆芯、海光等)、ARM(飞腾、鲲鹏、麒麟等)芯片架构。在OA办公、文档流转等各个Web系统中,实现最简单的打开编辑保存文件功能,调用PageOffice只需要几行代码就可以完成。后端代码在后端编写代码调用webOpen方法......
  • 文件IO学习【一】
    目录计算机的组成部分硬件系统软件系统文件系统Linux系统的目录根文件系统说明目录的结构分析Linux的文件类型计算机的组成部分硬件系统计算机的硬件主要是由五部分组成:控制器、运算器、存储器、输入设备、输出设备。运算器和控制器的总称是中央处理器(CPU),指的是计算机中对......
  • 自定义上传图片到服务器出现了上传失败的问题
    1、上传路径没改动这里在上传的时候发现存入路径是windows版本的//读取原始文件名StringfileName=file.getOriginalFilename();//获取后缀名StringsuffixName=fileName.substring(fileName.lastIndexOf("."));......
  • 工作流功能点列表
    支持功能功能描述完成程度父子流程主流程节点设置子流程,子流程节点会自动进入子流程,子流程结束后,主流程节点会自动跳转。✅顺序会签指同一个审批节点设置多个人,如A、B、C三人,三人按顺序依次收到待办,即A先审批,A提交后B才能审批,需全部同意之后,审批才可到下一审批......
  • 会充电的CANoe-赋能新能源汽车,高效完成即插即充(PnC)智能充电功能测试
     ISO15118-2标准中描述的PnC功能,可以实现插枪即充电,识别、计费信息、充电参数都通过高级别通信在EV和EVSE之间自动交换。简化了电动汽车的充电过程,提高了用户体验,为电动汽车行业带来了更智能、更便捷的充电解决方案。 然而,电动汽车和充电站之间要实现自动通信和计费,必须交......
  • C:$Mft(NTFS主文件表)C:$LogFile(NTFS卷日志)C:$BitMap(NTFS可用空间映射) C:$Mft$BITMAP C
    C:$Mft(NTFS主文件表)是NTFS文件系统中的一个重要组成部分。它是一个特殊的系统文件,用于记录NTFS分区中所有文件和目录的元数据信息。MFT实际上是MasterFileTable的缩写,意为主文件表。在NTFS文件系统中,每个文件和目录都有一个对应的记录,这些记录存储在MFT中。MFT中的每个记录......
  • 如何把多个文件(夹)随机复制到多个文件夹中
    首先,需要用到的这个工具:度娘网盘提取码:qwu2蓝奏云提取码:2r1z 先看文件的情况一共20个兔兔的图片,4个文件夹,把全部的图片随机的复制这些地方去打开工具,切换到文件批量复制版块找到右下角的设置,点击打开勾选“随机复制”,把文件进行随机的复制选中全部的兔兔图片,Ct......