尝试使用 Spring MVC 6.0.6 编写一个简单的文件上传处理程序。使用
POST
上传文件,编码为 multipart/form-data
。在服务器端,处理程序是
import jakarta.servlet.annotation.MultipartConfig;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
@Controller
@MultipartConfig
public class SimpleUpload {
@PostMapping(path = "/upload")
public ResponseEntity<String> uploadFile(@RequestParam("File") MultipartFile file) {
return file.isEmpty() ?
new ResponseEntity<String>(HttpStatus.NOT_FOUND) : new ResponseEntity<String>(HttpStatus.OK);
}
}
出现此错误:
Unable to process parts as no multi-part configuration has been provided
。
我已经阅读了有关此错误的其他答案,因此我添加了多部分配置,如下所示:
@EnableWebMvc
@Configuration
@Import({ApplicationConfig.class})
public class MvcConfig implements WebMvcConfigurer {
@Bean(name = "multipartResolver")
public MultipartResolver getMultipartResolver() {
return new StandardServletMultipartResolver();
}
@Bean(name = "filterMultipartResolver") // alternate name suggested by some people
public MultipartResolver getFilterMultipartResolver() {
return new StandardServletMultipartResolver();
}
}
它似乎不起作用,因为错误总是相同的。
应用中单元测试成功:
@WebAppConfiguration
@ContextConfiguration(classes = { MvcConfig.class, SimpleUpload.class })
@RunWith(SpringJUnit4ClassRunner.class)
public class MultipartPostRequestControllerUnitTest {
@Autowired
private WebApplicationContext webApplicationContext;
@Test
public void whenFileUploaded_thenVerifyStatus() throws Exception {
MockMultipartFile file = new MockMultipartFile("File",
"hello.txt",
MediaType.TEXT_PLAIN_VALUE,
"Hello, World!".getBytes());
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.build();
mockMvc.perform(multipart("/upload")
.file(file))
.andExpect(status().isOk());
}
}
但是通过 Postman 发送文件到 http://127.0.0.1:8080/upload 会返回 HTTP 状态 500,根本原因是
Unable to process parts as no multi-part configuration has been provided
。
我该如何解决这个问题?
使用Tomcat 10.1.7运行应用程序。
由于您已移至 spring 6,因此它将使用
jakarta.servlet-api
。另外,您已经使用了 spring-mvc,因此您必须在 web.xml 文件中进行配置,以使 servlet 知道它需要支持多部分请求。 @MultipartConfig
不适用于 web.xml。
您需要 1 颗豆子才能
StandardServletMultipartResolver
。
@Bean
MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
您需要更新
web.xml
添加<multipart-config />
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<multipart-config /> <!-- Add for supporting multipart request -->
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
spring 的文档
MultipartResolver
建议在方法customizeRegistration
中设置servlet的multipartConfig,但它仅在AbstractAnnotationConfigDispatcherServletInitializer.onStartup
中为默认的DispatcherServlet调用
因此,如果
onStartup
被覆盖,那么您需要自己在 servlet 上 setMultipartConfig
:
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
AnnotationConfigWebApplicationContext restContext = new AnnotationConfigWebApplicationContext();
restContext.register(RestServletConfig.class);
ServletRegistration.Dynamic restEntryPoint = servletContext.addServlet("rest-servlet", new DispatcherServlet(restContext));
restEntryPoint.setLoadOnStartup(1);
restEntryPoint.setAsyncSupported(isAsyncSupported());
restEntryPoint.addMapping("/");
long maxSize = 10L * 1024 * 1024 * 1024;
restEntryPoint.setMultipartConfig(new MultipartConfigElement(null, maxSize, maxSize, 0));
...
}
还有 spring 上下文中的 multipartResolver
@Bean
MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
我正在将我的应用程序从 Spring 5 更新到 Spring 6,我通过添加到我的
AbstractAnnotationConfigDispatcherServletInitializer
类扩展中解决了这个问题。
@Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
registration.setMultipartConfig(new MultipartConfigElement((String)null));
}