Whole Body Binding
For the cases where the names of the parts of the request cannot be known ahead of time, or the entire body should be read, a special type can be used to indicate the entire body is desired.
If a route has an argument of type MultipartBody (not to be confused with the class for the client) annotated with @Body, then each part of the request will be emitted through the argument. A MultipartBody is a publisher of CompletedPart instances.
For example:
Binding to the entire multipart body
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Post;
import io.micronaut.http.multipart.CompletedFileUpload;
import io.micronaut.http.multipart.CompletedPart;
import io.micronaut.http.server.multipart.MultipartBody;
import io.reactivex.Single;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
@Controller("/upload")
public class WholeBodyUploadController {
@Post(value = "/whole-body", consumes = MediaType.MULTIPART_FORM_DATA) (1)
public Single<String> uploadBytes(@Body MultipartBody body) { (2)
return Single.create(emitter -> {
body.subscribe(new Subscriber<CompletedPart>() {
private Subscription s;
@Override
public void onSubscribe(Subscription s) {
this.s = s;
s.request(1);
}
@Override
public void onNext(CompletedPart completedPart) {
String partName = completedPart.getName();
if (completedPart instanceof CompletedFileUpload) {
String originalFileName = ((CompletedFileUpload) completedPart).getFilename();
}
}
@Override
public void onError(Throwable t) {
emitter.onError(t);
}
@Override
public void onComplete() {
emitter.onSuccess("Uploaded");
}
});
});
}
}
Binding to the entire multipart body
import io.micronaut.http.MediaType
import io.micronaut.http.annotation.Body
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import io.micronaut.http.multipart.CompletedFileUpload
import io.micronaut.http.multipart.CompletedPart
import io.micronaut.http.server.multipart.MultipartBody
import io.reactivex.Single
import org.reactivestreams.Subscriber
import org.reactivestreams.Subscription
@Controller("/upload")
class WholeBodyUploadController {
@Post(value = "/whole-body", consumes = MediaType.MULTIPART_FORM_DATA) (1)
Single<String> uploadBytes(@Body MultipartBody body) { (2)
Single.<String>create({ emitter ->
body.subscribe(new Subscriber<CompletedPart>() {
private Subscription s
@Override
void onSubscribe(Subscription s) {
this.s = s
s.request(1)
}
@Override
void onNext(CompletedPart completedPart) {
String partName = completedPart.name
if (completedPart instanceof CompletedFileUpload) {
String originalFileName = ((CompletedFileUpload) completedPart).filename
}
}
@Override
void onError(Throwable t) {
emitter.onError(t)
}
@Override
void onComplete() {
emitter.onSuccess("Uploaded")
}
})
})
}
}
Binding to the entire multipart body
import io.micronaut.http.MediaType
import io.micronaut.http.annotation.Body
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import io.micronaut.http.multipart.CompletedFileUpload
import io.micronaut.http.multipart.CompletedPart
import io.micronaut.http.server.multipart.MultipartBody
import io.reactivex.Single
import org.reactivestreams.Subscriber
import org.reactivestreams.Subscription
@Controller("/upload")
class WholeBodyUploadController {
@Post(value = "/whole-body", consumes = [MediaType.MULTIPART_FORM_DATA]) (1)
fun uploadBytes(@Body body: MultipartBody): Single<String> { (2)
return Single.create { emitter ->
body.subscribe(object : Subscriber<CompletedPart> {
private var s: Subscription? = null
override fun onSubscribe(s: Subscription) {
this.s = s
s.request(1)
}
override fun onNext(completedPart: CompletedPart) {
val partName = completedPart.name
if (completedPart is CompletedFileUpload) {
val originalFileName = completedPart.filename
}
}
override fun onError(t: Throwable) {
emitter.onError(t)
}
override fun onComplete() {
emitter.onSuccess("Uploaded")
}
})
}
}
}