MultipartException:当前请求不是多部分请求。

65

我正在尝试创建一个RESTful控制器来上传文件。我看到了这个,并创建了以下控制器:

@RestController
public class MaterialController {

    @RequestMapping(value="/upload", method= RequestMethod.POST)
    public String handleFileUpload(
            @RequestParam("file") MultipartFile file){
        String name = "test11";
        if (!file.isEmpty()) {
            try {
                byte[] bytes = file.getBytes();
                BufferedOutputStream stream =
                        new BufferedOutputStream(new FileOutputStream(new File(name + "-uploaded")));
                stream.write(bytes);
                stream.close();
                return "You successfully uploaded " + name + " into " + name + "-uploaded !";
            } catch (Exception e) {
                return "You failed to upload " + name + " => " + e.getMessage();
            }
        } else {
            return "You failed to upload " + name + " because the file was empty.";
        }
    }
}

然后我使用Postman发送了一个PDF文件:

enter image description here

但服务器崩溃并显示以下错误:

.MultipartException: Current request is not a multipart request

我再次发现了这个问题,并添加了一个bean.xml文件。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    </bean>
</beans>

很遗憾,它仍然以相同的错误抱怨。


不知道是否导致了您的问题,但截图显示您没有为part命名。根据您的handleFileUpload()方法,您需要为part指定一个名称/键值为“file”。如果没有part名称,则可能没有将任何内容发送到服务器,“nothing”=“not multipart”。 - Andreas
不,你不需要创建一个目录。 - Andreas
由于您使用了@RestController注解类,因此您不需要在方法上注解@ResponseBody。请参阅javadoc:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RestController.html - Andreas
14个回答

67
当您在使用 Postman 进行多部分请求时,不要在 Header 中指定自定义的 Content-Type。因此,在 Postman 的 Header 标签中应为空白。Postman 将确定表单数据边界。在 Postman 的 Body 标签中,您应该选择表单数据并选择文件类型。您可以在 https://github.com/postmanlabs/postman-app-support/issues/576 找到相关讨论。

我没听懂你的意思。你能在 Postman 中发送正确请求的截图吗? - Sal-laS
2
在 Postman 的 Body 标签之前检查 Headers 标签。您的请求是正确的,但是您分享的图片显示了 Headers(1) 中的某个条目。请从那里删除该条目。 - abaghel

18

这种情况曾经发生在我身上:我有一个完美的Postman配置,但是在没有任何更改的情况下,即使我没有在Postman手动通知Content-Type,它也停止工作了。按照这个问题的答案,我尝试禁用标头并让Postman自动添加它,但两种选项都不起作用。

最终我解决了这个问题,方法是进入"Body"选项卡,将参数类型从File更改为Text,然后再改回File,重新选择要发送的文件;不知何故,这样就又可以工作了。在这种特定情况下,这似乎是一个Postman的bug吧?


3
非常感谢!只是从文本模式切换回选择文件,然后突然间它又可以工作了。 - Viktor Born
1
这对我有效,必须被接受。 - irshad.ahmad
1
我有同样的问题..谢谢 :) - d3rbastl3r
2
非常感谢您的回答。这个bug让我疯狂了,但解决方案相当简单。 - Sam Fisher
1
WTF: 真的。这个方法有效了,现在没问题了。谢谢。 - Maik

16

看起来问题是向服务器请求不是多部分请求。基本上,您需要修改客户端表单。例如:

<form action="..." method="post" enctype="multipart/form-data">
  <input type="file" name="file" />
</form>

希望这可以有所帮助。


2
这是一个REST应用程序,目前客户端没有HTML。我使用Postman。 - Sal-laS
@SalmanLashkarara,你仍然可以在你的REST客户端中添加它到头部。 - Sandeep Kumar

15

我之前在使用 Postman 进行 multipart 请求时,也遇到了同样的问题。我通过以下步骤解决了这个问题:

  • Headers 部分不要选择 Content-Type
  • PostmanBody 标签中选择 form-data 并选择相应的 file type

这对我来说起作用了。


5
在application.properties中,请添加以下内容:
spring.servlet.multipart.max-file-size=128KB
spring.servlet.multipart.max-request-size=128KB
spring.http.multipart.enabled=false

在您的HTML表单中,需要添加一个:enctype="multipart/form-data"
例如:
<form method="POST" enctype="multipart/form-data" action="/">

希望这能帮到你!

'spring.http.multipart.enabled'已被弃用,请使用'spring.servlet.multipart.enabled'。 - horvoje
2
您确定要将“启用”标志设置为“false”吗? - horvoje

2

请检查您在请求中选择的文件。

对我来说,我之所以出现错误是因为该文件不存在于系统中,因为我从其他计算机导入了该请求。


1
我曾经遇到过完全相同的问题!每个设置都是正确的 - 但有一件事:文件不存在了。 我总是得到 当前请求不是多部分请求,而不是得到“文件未找到”(或类似的内容)。 - cheneym

2

您需要在映射中添加consumes = {MULTIPART_FORM_DATA_VALUE}。完整示例:

@PostMapping(path = "/{idDocument}/attachments", consumes = {MULTIPART_FORM_DATA_VALUE})
ResponseEntity<String> addAttachmentsToDocumentForm(@PathVariable Long idDocument, @RequestParam("file") MultipartFile[] files){
    documentService.addAttachments(idDocument, files);
    return ok("your response");
}

2
在我的情况下,我从我的拦截器中删除了以下内容:

'Content-Type': 'application/json',

然后一切正常。
     intercept(httpRequest: HttpRequest<any>, httpHandler: HttpHandler): Observable<HttpEvent<any>> {
if (this.authService.isUserLoggedIn() && httpRequest.url.indexOf('login') === -1) {
  const authReq = httpRequest.clone({
    headers: new HttpHeaders({
    'Content-Type': 'application/json',
      Authorization: this.authService.getBasicAuth()
    })
  });
  return httpHandler.handle(authReq);
} else {
  return httpHandler.handle(httpRequest);
}}

2

enter image description here

 @PostMapping("/upload")
  public ResponseEntity<ResponseMessage> uploadFile(@RequestParam("file") MultipartFile uploadFile) {
    String message = "";
    try {
        service.save(uploadFile);

      message = "Uploaded the file successfully: " + uploadFile.getOriginalFilename();
      return ResponseEntity.status(HttpStatus.OK).body(new ResponseMessage(message));
    } catch (Exception e) {
      message = "Could not upload the file: " + uploadFile.getOriginalFilename() + "!";
      return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(new ResponseMessage(message));
    }
  }

1
在高级 REST 客户端 ARC 中,指定以下内容以使其正常工作:Content-Type multipart/form-data(这是头名称和头值)。这允许您将表单数据添加为键和值,现在可以根据您的 REST 规范指定字段名称,并从文件选择器中选择要上传的文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接