【问题标题】:Multipart File upload Spring Boot多部分文件上传 Spring Boot
【发布时间】:2014-10-31 05:23:36
【问题描述】:

我正在使用 Spring Boot 并希望使用 Controller 来接收分段文件上传。 发送文件时,我不断收到 error 415 unsupported content type 响应,并且永远无法到达控制器

There was an unexpected error (type=Unsupported Media Type, status=415).
Content type 'multipart/form-data;boundary=----WebKitFormBoundary1KvzQ1rt2V1BBbb8' not supported

我尝试在 html/jsp 页面中以及在使用 RestTemplate 的独立客户端应用程序中使用 form:action 发送。所有尝试都给出相同的结果

multipart/form-data;boundary=XXXXX not supported.

从多部分文档看来,边界参数必须添加到多部分上传中,但这似乎与接收 "multipart/form-data" 的控制器不匹配

我的控制器方法设置如下

@RequestMapping(value = "/things", method = RequestMethod.POST, consumes = "multipart/form-data" ,
                                     produces = { "application/json", "application/xml" })
     public ResponseEntity<ThingRepresentation> submitThing(HttpServletRequest request,
                                     @PathVariable("domain") String domainParam,
                                     @RequestParam(value = "type") String thingTypeParam,
                                     @RequestBody MultipartFile[] submissions) throws Exception

使用 Bean 设置

 @Bean
 public MultipartConfigElement multipartConfigElement() {
     return new MultipartConfigElement("");
 }

 @Bean
 public MultipartResolver multipartResolver() {
     org.springframework.web.multipart.commons.CommonsMultipartResolver multipartResolver = new org.springframework.web.multipart.commons.CommonsMultipartResolver();
     multipartResolver.setMaxUploadSize(1000000);
     return multipartResolver;
 }

如您所见,我已将消费类型设置为“multipart/form-data”,但是当发送多部分时,它必须有一个边界参数并放置一个随机边界字符串。

谁能告诉我如何设置控制器中的内容类型以匹配或更改我的请求以匹配我的控制器设置?

我尝试发送... 尝试 1...

<html lang="en">
<body>

    <br>
    <h2>Upload New File to this Bucket</h2>
    <form action="http://localhost:8280/appname/domains/abc/things?type=abcdef00-1111-4b38-8026-315b13dc8706" method="post" enctype="multipart/form-data">
        <table width="60%" border="1" cellspacing="0">
            <tr>
                <td width="35%"><strong>File to upload</strong></td>
                <td width="65%"><input type="file" name="file" /></td>
            </tr>
            <tr>
                <td>&nbsp;</td>
                <td><input type="submit" name="submit" value="Add" /></td>
            </tr>
        </table>
    </form>
</body>
</html>

尝试 2....

RestTemplate template = new RestTemplate();
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
parts.add("file", new FileSystemResource(pathToFile));

try{

    URI response = template.postForLocation(url, parts);
}catch(HttpClientErrorException e){
    System.out.println(e.getResponseBodyAsString());
}

尝试 3...

FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter();
        formHttpMessageConverter.setCharset(Charset.forName("UTF8"));


        RestTemplate restTemplate = new RestTemplate();

        restTemplate.getMessageConverters().add( formHttpMessageConverter );
        restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
        restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());

        MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
        map.add("file", new FileSystemResource(path));

        HttpHeaders imageHeaders = new HttpHeaders();
        imageHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);

        HttpEntity<MultiValueMap<String, Object>> imageEntity = new HttpEntity<MultiValueMap<String, Object>>(map, imageHeaders);
        ResponseEntity e=  restTemplate.exchange(uri, HttpMethod.POST, imageEntity, Boolean.class);
        System.out.println(e.toString());

【问题讨论】:

  • 你的域名是怎么写的?

标签: java spring spring-mvc spring-boot multipart


【解决方案1】:
@RequestBody MultipartFile[] submissions

应该是

@RequestParam("file") MultipartFile[] submissions

文件不是请求主体,它们是请求主体的一部分,并且没有内置的HttpMessageConverter 可以将请求转换为MultiPartFile 的数组。

您还可以将HttpServletRequest 替换为MultipartHttpServletRequest,这样您就可以访问各个部分的标题。

【讨论】:

  • 成功了,谢谢。我的所有客户端尝试现在都针对服务器端的此修复。原来我不需要 MultipartConfigElement 和 MultipartResolver bean。可能引导正在为我创建这些。
【解决方案2】:

您可以像这样简单地使用 controller 方法:

@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
@ResponseBody
public ResponseEntity<?> uploadFile(
    @RequestParam("file") MultipartFile file) {

  try {
    // Handle the received file here
    // ...
  }
  catch (Exception e) {
    return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
  }

  return new ResponseEntity<>(HttpStatus.OK);
} // method uploadFile

无需对 Spring Boot 进行任何额外配置。

使用以下html表单客户端:

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

如果您想设置文件大小限制,您可以在application.properties

# File size limit
multipart.maxFileSize = 3Mb

# Total request size for a multipart/form-data
multipart.maxRequestSize = 20Mb

此外,要使用 Ajax 发送文件,请看这里: http://blog.netgloo.com/2015/02/08/spring-boot-file-upload-with-ajax/

【讨论】:

    【解决方案3】:
       @Bean
        MultipartConfigElement multipartConfigElement() {
            MultipartConfigFactory factory = new MultipartConfigFactory();
            factory.setMaxFileSize("5120MB");
            factory.setMaxRequestSize("5120MB");
            return factory.createMultipartConfig();
        }
    

    把它放在你定义 bean 的类中

    【讨论】:

      【解决方案4】:

      最新版的 SpringBoot 也让上传多个文件变得非常容易。在浏览器端,您只需要标准的 HTML 上传表单,但具有 多个输入元素(每个要上传的文件一个,这非常重要),所有元素都具有相同的元素名称 (name="files"下面的例子)

      然后在服务器上的 Spring @Controller 类中你所需要的是这样的:

      @RequestMapping(value = "/upload", method = RequestMethod.POST)
          public @ResponseBody ResponseEntity<?> upload(
              @RequestParam("files") MultipartFile[] uploadFiles) throws Exception     
      {
          ...now loop over all uploadFiles in the array and do what you want
        return new ResponseEntity<>(HttpStatus.OK);
      }
      

      这些是棘手的部分。也就是说,知道创建多个输入元素,每个元素都命名为“文件”,并且知道使用 MultipartFile[](数组)作为请求参数是需要知道的棘手的事情,但就是这么简单。我不会讨论如何处理 MultipartFile 条目,因为已经有很多文档了。

      【讨论】:

        【解决方案5】:
        @RequestMapping(value="/add/image", method=RequestMethod.POST)
        public ResponseEntity upload(@RequestParam("id") Long id, HttpServletResponse response, HttpServletRequest request)
        {   
            try {
                MultipartHttpServletRequest multipartRequest=(MultipartHttpServletRequest)request;
                Iterator<String> it=multipartRequest.getFileNames();
                MultipartFile multipart=multipartRequest.getFile(it.next());
                String fileName=id+".png";
                String imageName = fileName;
        
                byte[] bytes=multipart.getBytes();
                BufferedOutputStream stream= new BufferedOutputStream(new FileOutputStream("src/main/resources/static/image/book/"+fileName));;
        
                stream.write(bytes);
                stream.close();
                return new ResponseEntity("upload success", HttpStatus.OK);
        
            } catch (Exception e) {
                e.printStackTrace();
                return new ResponseEntity("Upload fialed", HttpStatus.BAD_REQUEST);
            }   
        }
        

        【讨论】:

          【解决方案6】:

          在Controller中,你的方法应该是;

          @RequestMapping(value = "/upload", method = RequestMethod.POST)
              public ResponseEntity<SaveResponse> uploadAttachment(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
          ....
          

          此外,您需要更新 application.yml(或 application.properties)以支持最大文件大小和请求大小。

          spring:
              http:
                  multipart:
                      max-file-size: 5MB
                      max-request-size: 20MB
          

          【讨论】:

            【解决方案7】:

            添加@RequestPart 而不是@RequestParam

             public UploadFile upload(@RequestPart(name = "file")   MultipartFile multipartFile{
                //your code to process filee
                }
            

            【讨论】:

            • 我对此赞不绝口。
            猜你喜欢
            • 2014-05-01
            • 2022-10-22
            • 1970-01-01
            • 2019-11-10
            • 2021-05-29
            • 2019-07-24
            • 2017-11-05
            • 1970-01-01
            • 2015-10-16
            相关资源
            最近更新 更多