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.
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
curl on macOSCurrent Code
Request where no file is received
In this case,
/tmp/test.txtis an empty file, and the file parameter is bound asnull.Request where the file is received
In this case, the same empty file is bound as a
FilePart, andfile.filename()returnstest.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.