Skip to content

WebFlux loses empty multipart file when the file part is not last. #37264

Description

@taninchot

In my Spring Boot WebFlux application, I have a file upload use case. If the file is not empty, it will be uploaded. If the file is empty, the application will skip the upload and log the filename for tracking purposes.

The issue occurs when I upload an empty file. If the empty file is not the last part in the multipart request, it is received as null. However, if the empty file is the last part in the multipart request, it is still present.

Environment

  • Spring Boot: 4.1.1
  • Spring Framework: 7.0.9
  • Java: 17 in Maven configuration; the local test runtime used Java 21.0.11
  • Kotlin: 2.3.10
  • Application type: Spring WebFlux
  • Endpoint: POST /playground
  • Client: curl on macOS

Current Code

@RestController
class PlaygroundController {

    private val logger = LoggerFactory.getLogger(javaClass)

    @PostMapping("/playground", consumes = [MediaType.MULTIPART_FORM_DATA_VALUE])
    fun playground(
        @RequestPart("file", required = false) file: FilePart?,
        @RequestPart("action", required = false) action: String?,
        @RequestPart("collection_type", required = false) collectionType: String?,
        @RequestPart("reason", required = false) reason: String?,
    ): Mono<ResponseEntity<String>> {
        logger.info(
            "action={}, collection_type={}, reason={}, filename={}",
            action,
            collectionType,
            reason,
            file?.filename()
        )

        return Mono.just(
            file?.let {
                ResponseEntity.ok("Received file content: ${it.filename()}")
            } ?: ResponseEntity.ok("No file received")
        )
    }
}

Request where no file is received

curl --request POST \
      --url http://localhost:8080/playground \
      --form file=@/tmp/test.txt \
      --form action=asd

In this case, /tmp/test.txt is an empty file, and the file parameter is bound as null.

Request where the file is received

curl --request POST \
      --url http://localhost:8080/playground \
      --form action=asd \
      --form file=@/tmp/test.txt

In this case, the same empty file is bound as a FilePart, and file.filename() returns test.txt.

Expected Behavior

I would expect both requests to behave consistently. The order of multipart parts should not affect whether the empty file is bound.

In both cases, I would expect the file parameter to contain a FilePart and expose the filename test.txt, even though the file content is empty.

I found the following Spring Framework issues that appear related:

Both issues have already been closed, but the behavior I am seeing appears similar.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)type: bugA general bug

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions