如何用SpringBoot框架来接收multipart/form-data文件

 

今天遇到一个坑,这里给大家介绍一下。

想学习分布式、微服务、JVM、多线程、架构、java、python的童鞋,千万不要扫码,否则后果自负~

现在很多文件上传类型都是multipart/form-data类型的,HTTP请求如下所示:

 

可是问题就在于如果用传统的Struts2或者servlet等都可以很容易的实现文件接收的功能,例如下面的代码就可以实现:

boolean isMultipart = ServletFileUpload.isMultipartContent(request);//判断是否是表单文件类型  
DiskFileItemFactory factory = new DiskFileItemFactory();  
ServletFileUpload sfu = new ServletFileUpload(factory);  
List items = sfu.parseRequest(request);//从request得到所有上传域的列表  
for(Iterator iter = items.iterator();iter.hasNext();){  
    FileItem fileitem =(FileItem) iter.next();  
    if(!fileitem.isFormField()&&fileitem!=null){//判读不是普通表单域即是file  
        System.out.println("name:"+fileitem.getName());  
    }  
} 

可是今天我把这一段代码放在SpringBoot上面的时候就怎么也接收不到文件信息了,一直以为是前端什么数据传输错了。后来才知道原来SpringBoot有它自己的接收请求的代码。下面就给大家详细介绍一下它是如何实现这个功能的。

首选做一个简单的案例,也就是单个文件上传的案例。(这个案例是基于SpringBoot上面的,所以大家首先得搭建好SpringBoot这个框架)

前台HTML代码:

<html>  
<body>  
  <form action="/upload" method="POST" enctype="multipart/form-data">  
    <input type="file" name="file"/>  
    <input type="submit" value="Upload"/>   
  </form>  
</body>  
</html>  

 

后台接收代码:

/**   
     * 文件上传具体实现方法;   
     *    
     * @param file   
     * @return   
     */    
    @RequestMapping("/upload")    
    @ResponseBody    
    public String handleFileUpload(@RequestParam("file") MultipartFile file) {    
        if (!file.isEmpty()) {    
            try {    
                /*   
                 * 这段代码执行完毕之后,图片上传到了工程的跟路径; 大家自己扩散下思维,如果我们想把图片上传到   
                 * d:/files大家是否能实现呢? 等等;   
                 * 这里只是简单一个例子,请自行参考,融入到实际中可能需要大家自己做一些思考,比如: 1、文件路径; 2、文件名;   
                 * 3、文件格式; 4、文件大小的限制;   
                 */    
                BufferedOutputStream out = new BufferedOutputStream(    
                        new FileOutputStream(new File(    
                                file.getOriginalFilename())));    
                System.out.println(file.getName());  
                out.write(file.getBytes());    
                out.flush();    
                out.close();    
            } catch (FileNotFoundException e) {    
                e.printStackTrace();    
                return "上传失败," + e.getMessage();    
            } catch (IOException e) {    
                e.printStackTrace();    
                return "上传失败," + e.getMessage();    
            }    
    
            return "上传成功";    
    
        } else {    
            return "上传失败,因为文件是空的.";    
        }    
    }    

这样就可以实现对multipart/form-data类型文件的接收了。那如果是多个文件外加多个字段呢,下面接着看下一个多个文件上传的案例。

前台HTML界面:

<!DOCTYPE html>    
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"    
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">    
    <head>    
        <title>Hello World!</title>    
    </head>    
    <body>    
       <form method="POST" enctype="multipart/form-data" action="/batch/upload">     
           <p>文件1:<input type="text" name="id" /></p>    
           <p>文件2:<input type="text" name="name" /></p>    
           <p>文件3:<input type="file" name="file" /></p>    
           <p><input type="submit" value="上传" /></p>    
       </form>    
    </body>    
</html>     

后台接收代码:

@RequestMapping(value = "/batch/upload", method = RequestMethod.POST)    
      @ResponseBody    
      public String handleFileUpload(HttpServletRequest request) {    
        MultipartHttpServletRequest params=((MultipartHttpServletRequest) request);  
          List<MultipartFile> files = ((MultipartHttpServletRequest) request)    
                  .getFiles("file");   
          String name=params.getParameter("name");  
          System.out.println("name:"+name);  
          String id=params.getParameter("id");  
          System.out.println("id:"+id);  
          MultipartFile file = null;    
          BufferedOutputStream stream = null;    
          for (int i = 0; i < files.size(); ++i) {    
              file = files.get(i);    
              if (!file.isEmpty()) {    
                  try {    
                      byte[] bytes = file.getBytes();    
                      stream = new BufferedOutputStream(new FileOutputStream(    
                              new File(file.getOriginalFilename())));    
                      stream.write(bytes);    
                      stream.close();    
                  } catch (Exception e) {    
                      stream = null;    
                      return "You failed to upload " + i + " => "    
                              + e.getMessage();  
                  }    
              } else {    
                  return "You failed to upload " + i    
                          + " because the file was empty.";    
              }  
          }    
          return "upload successful";  
      }    

这样就可以实现对多个文件的接收了功能了。SpringBoot还可以对接收文件的格式还有个数等等进行限制,我这里就不多说了,大家有兴趣的可以自己去了解了解。

千万要记住SpringBoot对multipart/form-data类型的文件接收和其它是不一样的,大家以后遇到的时候要千万小心,不要像我一样一往无前的踩进去还傻傻的以为是前端的错误。

如果大家对文章有什么问题或者疑意之类的,可以加我订阅号在上面留言,订阅号上面我会定期更新最新博客。如果嫌麻烦可以直接加我wechat:lzqcode

 

 

已标记关键词 清除标记
**1、环境描述**:在springboot+swagger v_2.9.2的环境下 前后端分离,restful风格接口。 **2、提问原因**:前后端约定使用form-data进行数据传递,后台接口入参很多都是: public String findPage(String pageNo, String pageSize, Batch entity)这样的, **调试好swagger接口文档后发现**:如果将参数Batch用@Requestbody修饰,接口文档中的参数parameter就是聚合显示,如果后台没有使用@Requestbody修饰,那么swagger将递归该参数对象Batch的所有属性,包括其中的Page<Batch>,具体如下图: (![两种接收参数方式对swagger-ui的影响](https://img-ask.csdn.net/upload/201908/20/1566316583_639624.png) **图片描述**:(不知道图片看的清不) 同一个接口,仅仅只是入参对象的修饰语不同,在swagger上居然区别这么大 左边的swagger上看起来是正常的,网络上很多人都是用这种@Requestbody方式,但是我们约定的是form-data,所以不能使用@Requestbody接收参数。而如果不用,那么swagger文档上看到的都是全部铺开的,不是很方便使用。 **3、我尝试过的方法** 1.我想过两个方向,一个是修改后台swagger处理数据的拼装逻辑,另一个方向是在页面端修改数据的位置和逻辑,也就是修改api-doc接口返回的数据, **==第一个方向**:修改后台swagger处理数据的拼装结构,借鉴了(https://blog.csdn.net/u010579482/article/details/79990536) 中的一个思路,重写子类覆盖swagger主要处理参数数据的ModelAttributeParameterExpander,到目前为止还没有解决。 **==第二个方向**:修改页面端api-doc接口返回的数据,根据图上两种方式的对比,我们可以发现: **被@Requestbody修饰的入参对象**,在swagger-ui的definitions中已经有了一个对象的定义或声明: ![被@Requestbody修饰](https://img-ask.csdn.net/upload/201908/20/1566306781_529537.png) ![图片说明](https://img-ask.csdn.net/upload/201908/20/1566306934_308277.png) **而没有被@Requestbody修饰的返回结果**,在swagger-ui里返回结果就直接是在path.post.parameters中平铺在一起,也就是不方便所在,如果入参对象里有子对象,那递归出来就是一大片了。如下图: ![图片说明](https://img-ask.csdn.net/upload/201908/20/1566308568_957422.png) **4、现状:**到目前为止,还没有解决这个问题,各位大佬有时间的话教育下小弟,小弟在线等着,还望大佬们不吝赐教,[感激][感激][感激]
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页