Skip to content

List<MultipartFile> parameters incorrectly recognized as String in Swagger UI with org.springdoc:springdoc-openapi-starter-webmvc-ui:2.4.0 and above #2656

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
limehee opened this issue Jul 24, 2024 · 5 comments

Comments

@limehee
Copy link
Contributor

limehee commented Jul 24, 2024

Describe the bug

When receiving org.springframework.web.multipart.MultipartFile from the client, Swagger correctly handles the type. However, when MultipartFile is declared as a List, it incorrectly identifies the type as String. This issue appears to occur with versions of org.springdoc:springdoc-openapi-starter-webmvc-ui:2.4.0 and above.

To Reproduce
Steps to reproduce the behavior:

  1. Define an endpoint in Spring Boot that accepts a list of multipart files:
@Operation(summary = "[U] 게시판 파일 업로드", description = "ROLE_USER 이상의 권한이 필요함")
@PostMapping(value = "/api/v1/boards/files", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ApiResponse<List<String>> boardFileUpload(
    @RequestParam(name = "multipartFile", required = false) List<MultipartFile> multipartFiles
) throws IOException {
    List<String> filePaths = fileService.saveFiles(multipartFiles, "boards");
    return ApiResponse.success(filePaths);
}
  1. Use Swagger UI to test the endpoint.
  2. Notice that the multipartFile parameter is recognized as String instead of MultipartFile.
    Spring Boot version: 3.3.2
    Springdoc OpenAPI version: 2.4.0 and above

Expected behavior

Swagger should correctly identify the multipartFile parameter as a List<MultipartFile> instead of a String.

Screenshots

2.4.0 and above

image

2.3.0

image

Additional context
This issue occurs specifically with versions of org.springdoc:springdoc-openapi-starter-webmvc-ui:2.4.0 and above.

@dgswan
Copy link
Contributor

dgswan commented Aug 5, 2024

@limehee it looks like a duplicate of #2621. Please check here for the answer.

@limehee
Copy link
Contributor Author

limehee commented Aug 6, 2024

Thank you for your feedback on my issue.

I apologize for not noticing that this issue had already been reported. I appreciate you bringing it to my attention and providing the necessary information. I am sorry for any inconvenience this may have caused.

Thank you again for your assistance.

Best regards.

@limehee
Copy link
Contributor Author

limehee commented Aug 9, 2024

Hello Maintainer, @bnasslahsen

I recently encountered an issue with Springdoc OpenAPI version 2.4.0 and above, where using @RequestParam to handle multipart file uploads does not function as expected. I noticed in issue #2621 that a workaround involves using @RequestBody to resolve this problem. However, this approach seems to differ from the guidelines provided in the official Spring documentation, so I wanted to share a few concerns and ask for your thoughts.

Spring Documentation Guidelines

The official Spring documentation generally recommends using the @RequestParam annotation to handle multipart file uploads. For instance, consider the following example:

@Controller
public class FileUploadController {

    @PostMapping("/upload")
    public String handleFileUpload(@RequestParam("file") MultipartFile file) {
        if (!file.isEmpty()) {
            byte[] bytes = file.getBytes();
            // File processing logic
            return "redirect:uploadSuccess";
        }
        return "redirect:uploadFailure";
    }
}

@RequestParam is typically used to process query parameters and form data, including multipart data. This approach is widely followed and understood by many developers.

Issues with Using @RequestBody and @RequestPart

Currently, the suggested solution is to use @RequestBody for handling multipart file uploads. While this works, it raises some concerns:

  1. Compatibility with Existing Code: Many Spring applications already use @RequestParam, and switching to @RequestBody could have a significant impact across the codebase.

  2. Consistency with Official Documentation: Any divergence between the documentation and actual implementation might lead to confusion among developers and could potentially affect the consistency of the Spring framework's philosophy.

Suggestions and Questions

I believe it would be beneficial to either continue supporting @RequestParam for handling multipart file uploads or to offer an improved solution. If there is ongoing discussion or interest in enhancing this feature, I would be happy to contribute to the effort.

Additionally, if there was a specific reason for discontinuing support for @RequestParam in favor of @RequestBody, I would appreciate understanding the rationale behind this decision. Knowing the background would greatly help in aligning with the intended development direction.

For reference, here are the relevant Spring documentation links:

Thank you for your time and consideration.

Best regards.

@invokerbyxv
Copy link

Maybe you could try replacing @RequestParam with @RequestPart. After testing, the requesting party's code does not need to be changed.

The version I use:org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0

@Controller
public class FileUploadController {
    @PostMapping("/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public String handleFileUpload(
        @RequestPart("file") 
        @Schema(description = "just description", type = "file", format = "binary") 
        MultipartFile file
    ) {
        if (!file.isEmpty()) {
            byte[] bytes = file.getBytes();
            // File processing logic
            return "redirect:uploadSuccess";
        }
        return "redirect:uploadFailure";
    }
}

request code :

public static void main(String[] args) throws Exception {
    String filepath = "**********.pdf";
    HttpPost httpPost = new HttpPost("http://127.0.0.1:8080/upload");
    try (FileInputStream fileInputStream = new FileInputStream(filepath);
            CloseableHttpClient httpClient = HttpClientBuilder.create().build()){
        MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
        entityBuilder.setContentType(ContentType.MULTIPART_FORM_DATA);
        entityBuilder.addBinaryBody("file", fileInputStream, ContentType.APPLICATION_OCTET_STREAM,"**********.pdf");
        httpPost.setEntity(entityBuilder.build());
        String resString = httpClient.execute(httpPost, response -> EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));
        System.out.println(resString);
    }
}

@limehee
Copy link
Contributor Author

limehee commented Aug 28, 2024

Thank you for your suggestion. I tested using @RequestPart as you recommended, and it worked well. However, I believe that we should prioritize following Spring's official guidelines rather than changing code primarily for compatibility with the SpringDoc library. This was the reason behind my original feedback. I appreciate your input and wanted to share my thoughts on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants