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", consumes = MediaType.MULTIPART_FORM_DATA) (1)
  14. public Single<String> uploadBytes(@Body MultipartBody body) { (2)
  15. return Single.create(emitter -> {
  16. body.subscribe(new Subscriber<CompletedPart>() {
  17. private Subscription s;
  18. @Override
  19. public void onSubscribe(Subscription s) {
  20. this.s = s;
  21. s.request(1);
  22. }
  23. @Override
  24. public void onNext(CompletedPart completedPart) {
  25. String partName = completedPart.getName();
  26. if (completedPart instanceof CompletedFileUpload) {
  27. String originalFileName = ((CompletedFileUpload) completedPart).getFilename();
  28. }
  29. }
  30. @Override
  31. public void onError(Throwable t) {
  32. emitter.onError(t);
  33. }
  34. @Override
  35. public void onComplete() {
  36. emitter.onSuccess("Uploaded");
  37. }
  38. });
  39. });
  40. }
  41. }

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", consumes = MediaType.MULTIPART_FORM_DATA) (1)
  14. Single<String> uploadBytes(@Body MultipartBody body) { (2)
  15. Single.<String>create({ emitter ->
  16. body.subscribe(new Subscriber<CompletedPart>() {
  17. private Subscription s
  18. @Override
  19. void onSubscribe(Subscription s) {
  20. this.s = s
  21. s.request(1)
  22. }
  23. @Override
  24. void onNext(CompletedPart completedPart) {
  25. String partName = completedPart.name
  26. if (completedPart instanceof CompletedFileUpload) {
  27. String originalFileName = ((CompletedFileUpload) completedPart).filename
  28. }
  29. }
  30. @Override
  31. void onError(Throwable t) {
  32. emitter.onError(t)
  33. }
  34. @Override
  35. void onComplete() {
  36. emitter.onSuccess("Uploaded")
  37. }
  38. })
  39. })
  40. }
  41. }

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", consumes = [MediaType.MULTIPART_FORM_DATA]) (1)
  14. fun uploadBytes(@Body body: MultipartBody): Single<String> { (2)
  15. return Single.create { emitter ->
  16. body.subscribe(object : Subscriber<CompletedPart> {
  17. private var s: Subscription? = null
  18. override fun onSubscribe(s: Subscription) {
  19. this.s = s
  20. s.request(1)
  21. }
  22. override fun onNext(completedPart: CompletedPart) {
  23. val partName = completedPart.name
  24. if (completedPart is CompletedFileUpload) {
  25. val originalFileName = completedPart.filename
  26. }
  27. }
  28. override fun onError(t: Throwable) {
  29. emitter.onError(t)
  30. }
  31. override fun onComplete() {
  32. emitter.onSuccess("Uploaded")
  33. }
  34. })
  35. }
  36. }
  37. }