zoukankan      html  css  js  c++  java
  • (十二)springMvc 处理图片,视频等文件的上传

    导包

    需要导入如下的包

    commons-fileupload-1.3.3.jar
    commons-io-2.6.jar


    修改表单类型

    想要上传图片、文本、电影、音乐等资源的时候,需要将 form 的类型改为 multipart/form-data

    <form enctype="multipart/form-data">
    

    配置解析器

    springMvc.xml 文件中进行配置 ;

    <!--配置图片、音乐等文件的解析器-->
        <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <!--限制上文最大为5M 1024*1024*5-->
            <property name="maxInMemorySize">
                <value>5242880 </value>
            </property>
        </bean>
    

    处理上传的图片

    springMvc 对这类型的数据,也支持 参数绑定 ,使用 MultipartFile 接收 ,注意页面上的 name 属性的值和形参名一致,老生常谈的事了;

    MultipartFile 的一些基本操作 :

    //        获取上传的文件名
           String oldFile = multipartFile.getOriginalFilename() ;
    //       将上传的文件,从内存中写到硬盘上
           multipartFile.transferTo(path);
    

    补充一个自己写的工具类

    之前写的过于简单,补充下一个实例;
    
    1. 上传文件

      先判断 HttpServletRequest 是否是 MultipartHttpServletRequest 的实例,如果不是,则表示 HttpServletRequest 只是一个普通的 request ,并没有带文件过来,当然网上还有其他好几种判断方法,这是我常用的一种;

        public String upLoadExcel(HttpServletRequest request) {
              JSONObject jsonObject = new JSONObject();
              if (!(request instanceof MultipartHttpServletRequest)) {
                  jsonObject.put("result", "0");
                  jsonObject.put("resultInfo", "没有选中任何文件");
                  return jsonObject.toJSONString();
              }
              ...
       }
      

      如果HttpServletRequestMultipartHttpServletRequest 的实例,则进行强转,将 HttpServletRequest 转成 MultipartHttpServletRequest 的实例;然后获取上传的文件:

      首先说明下,上传的文件的情况,它是一个 Map 中套 List 的情况。

      因此,获取文件,需要先获取外层的 MapMultipartHttpServletRequest提供了获取其迭代器的方法:

      Iterator<String> iterator = request.getFileNames();
      

      这样就获取了所有的文件名,注意下 Map 里面套的是 List 因此,这些名字就是 Map 的键,一个键对应一个值 List ,就是说一个文件名可以对应多个文件。

      根据文件名获取其对应的 List :

      List<MultipartFile> files = request.getFiles(fileName);
      

      这样就获取到了一个文件对应的 Lsit 集合,再迭代这个 List 就可以获取其对应的文件。


      下面是一个实例:

      /**
           * 文件上传
           * <p>
           * 先遍历名字,在根据名字遍历对应的文件,两层循环,ok!
           *
           * @param request 接受提交文件的 request
           * @return 返回上传的文件的保存路径
           */
          public static List<String> fileUpload(MultipartHttpServletRequest request) throws IOException {
              List<String> paths = new ArrayList<>();
              // String path = FileUpDownloadUtils.class.getClassLoader().getResource("UpDownLoad" + File.separator + "readme.txt").getPath();
              // 当前web应用的绝对路径
              // String path = request.getSession().getServletContext().getRealPath("/") + "UpDownLoad";
              // 获取系统的路径
              String path = File.separator + "UpDownLoad";
              Iterator<String> iterator = request.getFileNames();
      
              while (iterator.hasNext()) {
                  String fileName = iterator.next();
                  List<MultipartFile> files = request.getFiles(fileName);
                  if (files.size() > 0) {
                      ListIterator<MultipartFile> multipartFileListIterator = files.listIterator();
                      while (multipartFileListIterator.hasNext()) {
                          String uuid = UUID.randomUUID().toString();
                          String path_in = getPathByHashcode(path, uuid);
                          MultipartFile multipartFile = multipartFileListIterator.next();
                          StringBuilder builder = new StringBuilder();
                          builder.append(path_in + File.separator);
                          builder.append(uuid + "_");
                          builder.append(multipartFile.getOriginalFilename());
                          File file = new File(builder.toString());
                          paths.add(file.getAbsolutePath());
                          multipartFile.transferTo(file);
                      }
                  }
              }
              return paths;
          }
      

      再附送下代码中,我写的文件随机分配算法,这是其中的一种实现,只适合代码去读文件,人工找某个文件比较费劲,还有一种实现是按照日期分配;

      日期分配,方便人工去拿文件,但是存在弱点,如果一天之内,有人暴力上传文件,文件夹就会被撑爆。各有各的优缺点。

          /**
       * 文件分配算法,根据UUid的值 算出文件保存的地址 ;
       * <p>
       * UUID 的长度是固定的,然后根据其长度,保证其生成的 hascode 的长度也是一样长的(32位)  ;
       * <p>
       * 每四位取为一个int 值 ,最多可以取 8 层 ;
       * <p>
       * 可以保存 16 * 16 * 16 * 16 * 1000 = 4 096 000(四百万份合同) ;
       *
       * @param path
       * @param uuid
       * @return
       */
      private static String getPathByHashcode(String path, String uuid) {
          int hashcode = uuid.hashCode();
          int one = hashcode & 0xf;
          int two = (hashcode >> 4) & 0xf;
          int three = (hashcode >> 4 >> 4) & 0xf;
          int four = (hashcode >> 4 >> 4 >> 4) & 0xf;
      
          File file = new File(path +
                  File.separator + one + File.separator + two
                  + File.separator + three + File.separator + four);
      
          if (!file.exists()) {
              file.mkdirs();
          }
      
          return file.getPath();
      }
      
    2. 下载文件

      导包都是导入 spring 框架下面的,不要导错了。做了下载文件的时候,对文件名的兼容性,可以有空格。

       /**
           * springMvc 的下载,原始的response的outputStream 怎么用的,都要忘记了 见鬼的框架,真香的封装
           *
           * @param imgPaths 封装需要下载的文件的路径
           * @return
           */
          public static ResponseEntity<Resource> fileDownload(String imgPaths, int blag) throws UnsupportedEncodingException {
      
              File file = new File(imgPaths);
              String simpleName = imgPaths.substring(imgPaths.indexOf("_") + 1);
      
              Resource body = new FileSystemResource(file);
              HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                      .getRequestAttributes()).getRequest();
      
              HttpStatus status = HttpStatus.CREATED;
      
              /**
               * 对文件名进行处理下
               */
              // 浏览器分为 火狐 和 非火狐
              if (request.getHeader("USER-AGENT").toLowerCase().indexOf("firefox") >= 0) {
                  // 火狐头大,需要独特设置一下
                  simpleName = new String(simpleName.getBytes("UTF-8"), "iso-8859-1");
              } else {
                  simpleName = URLEncoder.encode(simpleName, "UTF-8");
                  // IE 文件名有空格会被加号代替。需要自己替换回去
                  simpleName = simpleName.replaceAll("\+", "%20");
              }
      
      
              String suffix = simpleName.substring(simpleName.lastIndexOf(".") + 1);
              HttpHeaders headers = new HttpHeaders();
              switch (blag) {
                  /**
                   * 内嵌显示,针对IE浏览器:TEXT_PLAIN
                   * 文件名有空格。火狐则会截断文件名,需要将文件名用字符串包起来.使用 springMvc 不再需要这样做,并且你做了,还会在文件名前后各加一个 _ ;
                   *
                   * 预览需要自己判断下文件类型。
                   *
                   */
                  case SHOW:
                      MediaType mediaType;
                      switch (suffix.toLowerCase()) {
                          case "png":
                          case "jpg":
                          case "gif":
                              mediaType = MediaType.TEXT_PLAIN;
                              break;
                          // case "html":
                          // case "xml":
                          // case "markdown":
                          //     mediaType = MediaType.valueOf("text/" + suffix);
                          //     break;
                          default:
                              mediaType = MediaType.valueOf("application/" + suffix);
      
                      }
                      headers.setContentType(mediaType);
                      break;
                  /**
                   * 下载,下载设置内容格式为二进制数据:MediaType.APPLICATION_OCTET_STREAM
                   */
                  case DOWNLOAD:
                      headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
                      headers.setContentDispositionFormData("attachment", simpleName);
                      break;
              }
      
              headers.setContentLength(file.length());
              return new ResponseEntity<>(body, headers, status);
          }
      

      其中的常量是:

      传入 0 ,就只是显示在浏览器上,不下载,这个只显示功能还有点问题,图片、pdf等格式会显示,一些其他格式无论怎么调试都是会下载。。。 ; 1 是下载。

        public static final int SHOW = 0;
        public static final int DOWNLOAD = 1;
      
  • 相关阅读:
    cogs1538 [AHOI2005]LANE 航线规划
    cogs468 [NOI2010]超级钢琴
    [国家集训队2011]数颜色
    动态点分治总结
    点分治总结
    数论知识总结-欧拉函数
    BZOJ2683 简单题
    COGS1871 [国家集训队2011]排队(魏铭)
    LUOGU3278 [SCOI2013]多项式的运算
    BZOJ4491 我也不知道题目名字是什么
  • 原文地址:https://www.cnblogs.com/young-youth/p/11665652.html
Copyright © 2011-2022 走看看