无法处理零件,因为未提供多部分配置。

8

我写了一个简单的控制器来上传文件:

@RestEndpoint
public class ImageController {
    @Autowired
    GridFsTemplate mTemplate;

    @RequestMapping(value = "images", method = RequestMethod.POST)
    public @ResponseBody String testPhoto(@RequestParam String name, @RequestParam String directory, @RequestParam MultipartFile file) throws IOException {

        if(!file.isEmpty()){
            final byte[] bytes = file.getBytes();
            InputStream inputStream = new ByteArrayInputStream(bytes);
            mTemplate.store(inputStream, "name");

            return "uploaded photo";
        }

        return "failed";
    }

} 

@RestEndpoint注释是:

@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
public @interface RestEndpoint
{
    String value() default "";
}

我的ContextConfiguration类如下:

@Configuration
@EnableWebMvc
@ComponentScan(
    basePackages = "com.questter.site",
    useDefaultFilters = false,
    includeFilters =
    @ComponentScan.Filter({RestEndpoint.class, RestEndpointAdvice.class})
)
public class RestServletContextConfiguration extends WebMvcConfigurerAdapter {
    @Bean
    public CommonsMultipartResolver multiPartResolver(){

        CommonsMultipartResolver resolver = new CommonsMultipartResolver();
        return resolver;
    }
...
}

--- UPDATED ---

web.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
     version="3.1">

    <display-name>Spring Application</display-name>

    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.jsp</url-pattern>
            <url-pattern>*.jspf</url-pattern>
            <page-encoding>UTF-8</page-encoding>
            <scripting-invalid>true</scripting-invalid>
            <include-prelude>/WEB-INF/jsp/base.jspf</include-prelude>
            <trim-directive-whitespaces>true</trim-directive-whitespaces>
            <default-content-type>text/html</default-content-type>
        </jsp-property-group>
    </jsp-config>

    <!--<context-param>-->
        <!--<param-name>spring.profiles.active</param-name>-->
        <!--<param-value>development</param-value>-->
    <!--</context-param>-->

    <session-config>
        <session-timeout>30</session-timeout>
        <cookie-config>
            <http-only>true</http-only>
        </cookie-config>
        <tracking-mode>COOKIE</tracking-mode>
    </session-config>

    <distributable />

</web-app>

---- UPDATED ----

public class Bootstrap implements WebApplicationInitializer
{

    @Override
    public void onStartup(ServletContext container) throws ServletException
    {
        container.getServletRegistration("default").addMapping("/resource/*");

        AnnotationConfigWebApplicationContext rootContext =
            new AnnotationConfigWebApplicationContext();
        rootContext.register(RootContextConfiguration.class);
        container.addListener(new ContextLoaderListener(rootContext));

        AnnotationConfigWebApplicationContext webContext =
            new AnnotationConfigWebApplicationContext();
        webContext.register(WebServletContextConfiguration.class);
        ServletRegistration.Dynamic dispatcher = container.addServlet(
            "springWebDispatcher", new DispatcherServlet(webContext)
        );
        dispatcher.setLoadOnStartup(1);
        dispatcher.setMultipartConfig(new MultipartConfigElement(
            null, 20_971_520L, 41_943_040L, 512_000
        ));
        dispatcher.addMapping("/");

        AnnotationConfigWebApplicationContext restContext =
                new AnnotationConfigWebApplicationContext();
        restContext.register(RestServletContextConfiguration.class);
        DispatcherServlet servlet = new DispatcherServlet(restContext);
        servlet.setDispatchOptionsRequest(true);
        dispatcher = container.addServlet(
                "springRestDispatcher", servlet
        );
        dispatcher.setLoadOnStartup(2);
        dispatcher.addMapping("/rest/*");

        rootContext.refresh();
        DbBootstrap dbBootstrap = rootContext.getBean(DbBootstrap.class);
        dbBootstrap.init();

    }


}

当执行一个POST请求(使用Postman)时,我得到了以下错误信息:

HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalArgumentException:Expected MultipartHttpServletRequest: is a MultipartResolver configured 

我在stackoverflow上查看了一些类似的问题,但没有答案能够帮到我。

Spring版本号为4.0.4

非常感谢任何帮助(当然要点赞)。

谢谢。


请展示您的web.xml文件或相当的Java配置。 - Sotirios Delimanolis
@SotiriosDelimanolis 更新了问题。谢谢! - royB
我想看看你的 WebAppInitializer - Sotirios Delimanolis
@SotiriosDelimanolis更新了引导代码。再次感谢。 - royB
请求是否正确发送到REST调度程序? - Sotirios Delimanolis
是的。请求:localhost:8080/rest/images - royB
4个回答

16

我不知道他们为什么这样做,但上下文中的MultipartResolver bean需要命名为multipartResolver。将你的@Bean方法重命名为

public CommonsMultipartResolver multipartResolver(){ // lowercase 'P'

或者明确地给它命名

@Bean(name = "multipartResolver")
public CommonsMultipartResolver canBeCalledAnything(){

5
allowCasualMultipartParsing="true"

在context.xml文件中的context标签,对我来说起作用了。


2
不,这是Tomcat Servlet容器特定的配置。OP所说的错误是Spring MVC错误,其中缺少了“MultipartResolver”bean。 - Sotirios Delimanolis

2
从异常信息可以看出,没有找到多部分配置。尽管您提供了“multipartResolver”bean。
问题在于,在Spring Security过滤器之前指定MultipartFilter时,它会尝试获取“multipartResolver”bean,但找不到它。因为它期望bean名称/ID为“filterMultipartResolver”,而不是“multipartResolver”。
请做自己一个忙。请像以下示例一样更改bean配置 -
@Bean
public CommonsMultipartResolver filterMultipartResolver(){
    CommonsMultipartResolver resolver = new 
    CommonsMultipartResolver();
    return resolver;
}

或者
@Bean(name = "filterMultipartResolver")
public CommonsMultipartResolver multiPartResolver(){
    CommonsMultipartResolver resolver = new 
    CommonsMultipartResolver();
    return resolver;
}

上面被接受的答案对我有用。也许你的答案适用于另一种情况。 - arthur
我认为这是由于版本的原因。被接受的答案对我没有起作用。我进行了更多的研究,发现更改bean名称解决了这个问题。 - Ramjan Ali

0

R. Ali Ashik的答案对我很有用。

以下是我正在工作的项目的pom.xml的相关部分:

  <properties>
  <springframework.version>5.0.2.RELEASE</springframework.version>
  <springsecurity.version>5.0.0.RELEASE</springsecurity.version>
  <hibernate.version>5.2.17.Final</hibernate.version>
  <mysql.connector.version>8.0.11</mysql.connector.version>

因为我有一个自定义的登录页面和持久化身份验证设置,所以我还需要以下内容:

public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

        @Override
        protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
            insertFilters(servletContext, new MultipartFilter());
        }
    }

但实际上最关键的是,正如R. Ali Ashik所指出的:

@Bean(name = "filterMultipartResolver")
public CommonsMultipartResolver multiPartResolver(){
    CommonsMultipartResolver resolver = new 
    CommonsMultipartResolver();
    return resolver;
}

上下文中相关的参考资料是这个: Class MultipartFilter

相关的文本如下:

Looks up the MultipartResolver in Spring's root web application context. Supports a "multipartResolverBeanName" filter init-param in web.xml; the default bean name is "filterMultipartResolver". Looks up the MultipartResolver on each request, to avoid initialization order issues (when using ContextLoaderServlet, the root application context will get initialized after this filter).

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