详解弹簧引导中补丁上传文件的问题

  

弹簧引导中上传多部分/格式文件只能是提后交,而不针对补丁,这个问题花了作者26个小时才解决这个问题,最后不得不调试春源代码来解决这个问题。

  

需求:在网页中构建一个表单,其中包含一个文本输入字段和一个用于文件上载的输入。很简单。这是表单:

        & lt;形式id=笆荨狈椒?安苟 盿ction="/f”比;   & lt;输入类型=拔谋尽北匦璧膎ame=肮尽北?   & lt;输入类型=拔募币髇ame="定义"/比;   & lt;/form>      

RestController中的方法:

        @RequestMapping (value=" https://www.yisu.com/f ",方法=补丁)   公共空间上传(   @RequestPart MultipartFile定义(“定义”),   @RequestPart公司(“公司”)字符串   ){…}   之前      

注意它是补丁的方法(根据要求)而不是,部分要求是提交的ajax请求,并不是表单提交,代码如下:

        var fileInput=?//这是html元素保存文件   var textInput=?//这是字符串   var fd=new FormData ();   fd.append(“定义”,fileInput.files [0]);   fd。追加(“名字”,textInput);   xhr=new XMLHttpRequest ();   xhr。(“补丁”,uploadForm开放。行动,真正的);   xhr。发送(fd);   之前      

但无论怎么做,我都无法让它发挥作用。总是遇到以下异常:

  
  

MissingServletRequestPartException:需要请求“定义”部分不存在
  

     

我做的第一件事就是将这个问题分解为最简单的问题,所以我将请求类型更改为POST,并删除了textInput。将多部分解析器的实现进行更改,从org.springframework.web.multipart.support。StandardServletMultipartResolver改为org.springframework.web.multipart.commons.CommonsMultipartResolver

        @ configuration   公开课MyConfig {      @ bean   公共MultipartResolver MultipartResolver () {   返回新CommonsMultipartResolver ();   }   }      之前      

这还需要将commons-fileupload库添加到类路径中。

  

但每当我添加一个字符串变量返回错误:字符串字段而不是文件字段

  

这说明多声部请求解析器没有发现这部分字段。

  

这是由于Javascript的FormData问题,在FormData对象上调用的附加方法接受两个参数名称和值(有第三个但不重要),该值字段可以是一个USVString或Blob(包括子类等文件)。更改代码为:

        var fileInput=?//这是html元素保存文件   var textInput==新团((“信息”),{   类型:“文本/普通”   });   ;//这是字符串   var fd=new FormData ();   fd.append(“定义”,fileInput.files [0]);   fd。追加(“名字”,textInput);   xhr=new XMLHttpRequest ();   xhr。(“补丁”,uploadForm开放。行动,真正的);   xhr。发送(fd);   之前      

它突然开始工作:)。

  

看一下浏览器发送的内容:

  
  

——WebKitFormBoundaryHGN3YjdgsELbgmZH
  附加:格式;name="定义";文件名="测试。csv”内容类型:文本/csv
  这是一个文件的内容,浏览器隐藏它。
  ——WebKitFormBoundaryHGN3YjdgsELbgmZH附加项:格式;name="名称"
  这是字符串
  - - - - - - - - WebKitFormBoundaryHGN3YjdgsELbgmZH
  

     

你能注意到内容处置标题中缺少的内容吗?文件名和内容类型。在servlet处理期间,多部分表单变成MultipartFile。在commons-fileupload中有一行:

        字符串subContentType=headers.getHeader (CONTENT_TYPE);   如果(subContentType !=null…) {}      

这是得到的内容类型,如果它是null,则处理是通过不同的路由将我们的上传部分不是转为MultipartFile,而是转换为MultipartParameter(放在不同的地图中,而春天没有找到它),然后弹簧为每个参数创建单独的实例,形成在调用其他方法时实现绑定的表单。

  

RequestPartServletServerHttpRequest构造函数中可以找到抛出异常的位置:

        HttpHeaders header=this.multipartRequest.getMultipartHeaders (this.partName);   如果(标题==null) {   把新MissingServletRequestPartException (partName);   }   之前      

重要的是getMultipartHeaders只查看多部分的文件文件而不是参数参数。

  

这就是为什么添加具有特定类型的blob解决了问题的原因:

详解弹簧引导中补丁上传文件的问题