Uploading an array of MultipartFile objects using Swagger-UI to the Spring Boot app?

Viewed 3441

I'm trying to upload array of .pdf/.docx/.whatever.

As per Swagger's docs they do enable sending an array of files. I just don't know how to tell Swagger-UI to create that kind of request.

I have following dependencies for Swagger (not sure whether this refers to OAS2 or OAS3):

    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.9.2</version>
    </dependency>

    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.9.2</version>
    </dependency>

Here is my SwaggerConfig class (placed within package of main Spring Boot function):

@Configuration
@EnableSwagger2
public class SwaggerConfig { 

    @Bean
    public Docket swaggerPlugin() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .paths(PathSelectors.any())
                .apis(RequestHandlerSelectors.any())
                .build()
                
                .securitySchemes(Arrays.asList(apiKey()))
                .securityContexts(Arrays.asList(securityContext()))
                .apiInfo(metaData());
    }

    private ApiInfo metaData() {
        return new ApiInfoBuilder()
                .title("Spring Boot REST API - Garbage Collectors App")
                .description("*")
                .version("1.0.0")
                .license("Apache License Version 2.0")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
                .build();
    }

    @Bean
    public SecurityConfiguration security() {
        return SecurityConfigurationBuilder.builder().scopeSeparator(",")
                .additionalQueryStringParams(null)
                .useBasicAuthenticationWithAccessCodeGrant(false).build();
    }

    private ApiKey apiKey() {
        return new ApiKey("apiKey", "Authorization", "header");
    }

    private SecurityContext securityContext() {
        return SecurityContext.builder().securityReferences(defaultAuth())
                .forPaths(PathSelectors.any()).build();
    }

    private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope(
                "global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return Arrays.asList(new SecurityReference("apiKey",
                authorizationScopes));
    }

    @Bean
    UiConfiguration uiConfig() {
        return UiConfigurationBuilder.builder()
                .deepLinking(true)
                .displayOperationId(false)
                .defaultModelsExpandDepth(1)
                .defaultModelExpandDepth(1)
                .defaultModelRendering(ModelRendering.EXAMPLE)
                .displayRequestDuration(true)
                .docExpansion(DocExpansion.NONE)
                .filter(false)
                .maxDisplayedTags(null)
                .operationsSorter(OperationsSorter.ALPHA)
                .showExtensions(false)
                .tagsSorter(TagsSorter.ALPHA)
                .supportedSubmitMethods(UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS)
                .validatorUrl(null)
                .build();
    }

}

Also, here is the controller I'm using:

@ApiParam(allowMultiple=true) 
@RequestMapping(value = "/send/email", consumes = {"multipart/form-data"}, method = RequestMethod.POST) 
    public String sendEmail(@RequestParam("attachments") MultipartFile[] attachments) throws IOException {
        
        System.out.println(attachments.length);
        
        return "test";
}

I'm able to pick an array of files from file system:

enter image description here

But after sending request I get following error:

{
      "timestamp": "2020-12-22T18:29:29.578+00:00",
      "status": 400,
      "error": "Bad Request",
      "trace": "org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'attachments' is not present org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:199)\r\n\tat org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:114)\r\n\tat org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:170)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)\r\n\tat
}

On the other hand single MultipartFile upload and any number of individually pre-determined MultipartFile can be uploaded without any problems.

What did I else tried:

-going over google inside and out -reading the docs: In here I can see that they made a fix on the issue but I still don't know how to tell Swagger-UI to make request which I'm specifying on server-side, no matter which dependency version I user. -try to set application.ymal like so:

 requestBody:
    content:
      multipart/form-data:
        schema:
          type: object
          properties:
            orderId:
              type: integer
            userId:
              type: integer
            fileName:
              type: string
              format: binary

Also, I've tried these two dependencies:

        <dependency>
            <groupId>io.springfox</groupId>
         <artifactId>springfox-swagger-ui</artifactId>
            <version>3.0.0</version>
    </dependency>
    
    
    <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>   
    </dependencies>

My last solution is to allow sending up to 2-3 MultipartFile, but I would really like to avoid this. How can I configure this?

1 Answers
Related