'How can I specify a multipart file upload with params

I'm trying to document an API method that will receive a file and two parameters as int. Using swagger editor I was able to describe what I want, but couldn't replicate that using annotations.

what I want

This is what I draw on swagger editor

requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                flow:
                  type: integer
                environment:
                  type: integer
                file:
                  type: string
                  format: binary
        required: true

If I use consumes = MediaType.MULTIPART_FORM_DATA I get the params. And if I use consumes = MediaType.APPLICATION_OCTET_STREAM I get the file to upload.

failed attemp 1 failed attemp 2

@Operation(summary = "Unpack Files",
            description = "Receives a packed zip or gzip file with xml files inside or receives xml files",
            security = @SecurityRequirement(name = "apiKey"),
            responses = {
                    @ApiResponse(responseCode = "201", description = "Created"),
                    @ApiResponse(responseCode = "400", description = "Something Went Wrong"),
                    @ApiResponse(responseCode = "401", description = "Unauthorized"),
                    @ApiResponse(responseCode = "503", description = "Service Unavailable")
            },
            requestBody = @RequestBody(
                content = @Content(
                    mediaType = MediaType.MULTIPART_FORM_DATA,
                    schema = @Schema(implementation = Document.class, format = "binary"),
                    encoding = @Encoding(
                            name = "file",
                            contentType = "application/xml, application/zip, application/gzip"
                    )
                ),
                required = true
            )
    )
    @Post(value = "/unpack", consumes = MediaType.APPLICATION_OCTET_STREAM)
    public Single<HttpResponse<String>> upload(StreamingFileUpload file, int flow, int environment) throws IOException {
        return Single.just(new Document(file.getFilename(), environment, flow))
            .flatMap(DocumentValidation::validateDocumentExtension)
            .doOnError(throwable -> {
                log.error("Validation exception: {}", throwable.getMessage());
                exception = throwable.getMessage();
            })
            .doOnSuccess(doc -> {
                log.info("File saved successfuly");
                File tempFile = File.createTempFile(file.getFilename(), "temp");
                file.transferTo(tempFile);
            })
            .map(success -> {
                if (exception != null || !exception.equals("")) {
                    return HttpResponse.<String>status(HttpStatus.CREATED).body("Uploaded");
                } else {
                    return HttpResponse.<String>status(HttpStatus.SERVICE_UNAVAILABLE).body(exception);
                }
            }
        );
    }

Thanks in advance.



Solution 1:[1]

Looks like missing @QueryValue

From documentation 6.4 Simple Request Binding:

Bindings from a request URI variable or request parameter | @QueryValue String myParam

From documentation 6.19 File Uploads:

The method is set to consume MULTIPART_FORM_DATA

The method parameters match form attribute names. In this case the file will match for example an

The StreamingFileUpload.transferTo(java.lang.String) method is used to transfer the file to the server.

Kotlin simple:

@Controller
class SomeController {

    @Post(value = "/", consumes = [MediaType.MULTIPART_FORM_DATA])
    fun upload(file: StreamingFileUpload,
               @QueryValue flow: Int,
               @QueryValue environment: Int): Single<HttpResponse<String>> {
        val tempFile = File.createTempFile(file.filename, "temp")
        return Single.fromPublisher(file.transferTo(tempFile))
                .map { success ->
                    if (success) {
                        HttpResponse.ok("Uploaded");
                    } else {
                        HttpResponse.status<String>(HttpStatus.CONFLICT)
                                .body("Upload Failed")
                    }
                }
    }

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1