Spring MVC 多部分配置

问题描述 投票:0回答:3

尝试使用 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运行应用程序。

java spring-mvc file-upload upload
3个回答
4
投票

由于您已移至 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>

0
投票

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();
}

0
投票

我正在将我的应用程序从 Spring 5 更新到 Spring 6,我通过添加到我的

AbstractAnnotationConfigDispatcherServletInitializer
类扩展中解决了这个问题。

@Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
  registration.setMultipartConfig(new MultipartConfigElement((String)null));
}
© www.soinside.com 2019 - 2024. All rights reserved.