Wrapper
Wrapper

Reputation: 932

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

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?

Upvotes: 4

Views: 6894

Answers (1)

Ashutosh Srivastav
Ashutosh Srivastav

Reputation: 669

You can't do this in Swagger 2.x. As per Swagger doc.

However, uploading an arbitrary number of files (an array of files) is not supported. There is an open feature request at https://github.com/OAI/OpenAPI-Specification/issues/254. For now, you can use a binary string array as a workaround for uploading an arbitrary number of files:

Swagger 2 Documentation

Upvotes: 1

Related Questions