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

  1. import io.micronaut.http.MediaType;
  2. import io.micronaut.http.annotation.Body;
  3. import io.micronaut.http.annotation.Controller;
  4. import io.micronaut.http.annotation.Post;
  5. import io.micronaut.http.multipart.CompletedFileUpload;
  6. import io.micronaut.http.multipart.CompletedPart;
  7. import io.micronaut.http.server.multipart.MultipartBody;
  8. import io.reactivex.Single;
  9. import org.reactivestreams.Subscriber;
  10. import org.reactivestreams.Subscription;
  11. @Controller("/upload")
  12. public class WholeBodyUploadController {
  13. @Post(value = "/whole-body",
  14. consumes = MediaType.MULTIPART_FORM_DATA,
  15. produces = MediaType.TEXT_PLAIN) (1)
  16. public Single<String> uploadBytes(@Body MultipartBody body) { (2)
  17. return Single.create(emitter -> {
  18. body.subscribe(new Subscriber<CompletedPart>() {
  19. private Subscription s;
  20. @Override
  21. public void onSubscribe(Subscription s) {
  22. this.s = s;
  23. s.request(1);
  24. }
  25. @Override
  26. public void onNext(CompletedPart completedPart) {
  27. String partName = completedPart.getName();
  28. if (completedPart instanceof CompletedFileUpload) {
  29. String originalFileName = ((CompletedFileUpload) completedPart).getFilename();
  30. }
  31. }
  32. @Override
  33. public void onError(Throwable t) {
  34. emitter.onError(t);
  35. }
  36. @Override
  37. public void onComplete() {
  38. emitter.onSuccess("Uploaded");
  39. }
  40. });
  41. });
  42. }
  43. }

Binding to the entire multipart body

  1. import io.micronaut.http.MediaType
  2. import io.micronaut.http.annotation.Body
  3. import io.micronaut.http.annotation.Controller
  4. import io.micronaut.http.annotation.Post
  5. import io.micronaut.http.multipart.CompletedFileUpload
  6. import io.micronaut.http.multipart.CompletedPart
  7. import io.micronaut.http.server.multipart.MultipartBody
  8. import io.reactivex.Single
  9. import org.reactivestreams.Subscriber
  10. import org.reactivestreams.Subscription
  11. @Controller("/upload")
  12. class WholeBodyUploadController {
  13. @Post(value = "/whole-body",
  14. consumes = MediaType.MULTIPART_FORM_DATA,
  15. produces = MediaType.TEXT_PLAIN) (1)
  16. Single<String> uploadBytes(@Body MultipartBody body) { (2)
  17. Single.<String>create({ emitter ->
  18. body.subscribe(new Subscriber<CompletedPart>() {
  19. private Subscription s
  20. @Override
  21. void onSubscribe(Subscription s) {
  22. this.s = s
  23. s.request(1)
  24. }
  25. @Override
  26. void onNext(CompletedPart completedPart) {
  27. String partName = completedPart.name
  28. if (completedPart instanceof CompletedFileUpload) {
  29. String originalFileName = ((CompletedFileUpload) completedPart).filename
  30. }
  31. }
  32. @Override
  33. void onError(Throwable t) {
  34. emitter.onError(t)
  35. }
  36. @Override
  37. void onComplete() {
  38. emitter.onSuccess("Uploaded")
  39. }
  40. })
  41. })
  42. }
  43. }

Binding to the entire multipart body

  1. import io.micronaut.http.MediaType
  2. import io.micronaut.http.annotation.Body
  3. import io.micronaut.http.annotation.Controller
  4. import io.micronaut.http.annotation.Post
  5. import io.micronaut.http.multipart.CompletedFileUpload
  6. import io.micronaut.http.multipart.CompletedPart
  7. import io.micronaut.http.server.multipart.MultipartBody
  8. import io.reactivex.Single
  9. import org.reactivestreams.Subscriber
  10. import org.reactivestreams.Subscription
  11. @Controller("/upload")
  12. class WholeBodyUploadController {
  13. @Post(value = "/whole-body",
  14. consumes = [MediaType.MULTIPART_FORM_DATA],
  15. produces = [MediaType.TEXT_PLAIN]) (1)
  16. fun uploadBytes(@Body body: MultipartBody): Single<String> { (2)
  17. return Single.create { emitter ->
  18. body.subscribe(object : Subscriber<CompletedPart> {
  19. private var s: Subscription? = null
  20. override fun onSubscribe(s: Subscription) {
  21. this.s = s
  22. s.request(1)
  23. }
  24. override fun onNext(completedPart: CompletedPart) {
  25. val partName = completedPart.name
  26. if (completedPart is CompletedFileUpload) {
  27. val originalFileName = completedPart.filename
  28. }
  29. }
  30. override fun onError(t: Throwable) {
  31. emitter.onError(t)
  32. }
  33. override fun onComplete() {
  34. emitter.onSuccess("Uploaded")
  35. }
  36. })
  37. }
  38. }
  39. }