4

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?

2
  • 1
    You need Springfox 3.0 or springdoc-openapi to upload arrays of files - these versions generate OpenAPI 3.0 definitions (where file arrays are supported) instead of OpenAPI 2.0. Here's how the YAML should look like. Commented Dec 22, 2020 at 19:45
  • (cont.) I don't know the exact Java annotations that would generate this YAML, but maybe start with the multipart example provided here, replace individual files with an array and use something like @Parameter(array = @ArraySchema(type = "string", format = "binary")) Commented Dec 22, 2020 at 19:45

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.