import ballerina/http;
import ballerina/mime;
import ballerina/io;endpoint http:Listener multipartEP {
    port:9090
};@http:ServiceConfig {basePath:"/nestedparts"}
service<http:Service> test bind multipartEP {
    @http:ResourceConfig {
      methods:["POST"],
      path:"/decoder"
    }
    nestedPartReceiver (endpoint conn, http:Request req)  {
        http:Response res = new;
        match req.getMultiparts() {
            mime:EntityError err => {
                res.setStringPayload("Error occurred while decoding parent parts!");
                res.statusCode = 500;
            }
            mime:Entity[] parentParts => {
                int i = 0;
                while (i < lengthof parentParts) {
                    mime:Entity parentPart = parentParts[i];
                    handleNestedParts(parentPart);
                    i = i + 1;
                }
                res.setStringPayload("Nested Parts Received!");
            }
        }
        _ = conn -> respond(res);
    }
}
function handleNestedParts (mime:Entity parentPart) {
    string contentTypeOfParent = parentPart.contentType.toString();
    if (contentTypeOfParent.hasPrefix("multipart/")) {
        match parentPart.getBodyParts() {
            mime:EntityError err => {
                io:println("Error retrieving child parts!");
            }
            mime:Entity[] childParts => {
            int i = 0;
            io:println("Nested Parts Detected!");
                while (i < lengthof childParts) {
                    mime:Entity childPart = childParts[i];
                    handleContent(childPart);
                    i = i + 1;
                }
            }
        }
    }
}
function handleContent (mime:Entity bodyPart) {
    string contentType = bodyPart.contentType.toString();
    if (mime:APPLICATION_XML == contentType || mime:TEXT_XML == contentType) {
        var payload = bodyPart.getXml();
        match payload {
            mime:EntityError err => io:println("Error in getting xml payload");
            xml xmlContent => io:println(xmlContent);
        }
    } else if (mime:APPLICATION_JSON == contentType) {
        var payload = bodyPart.getJson();
        match payload {
            mime:EntityError err => io:println("Error in getting json payload");
            json jsonContent => io:println(jsonContent);
        }
    } else if (mime:TEXT_PLAIN == contentType) {
        var payload = bodyPart.getText();
        match payload {
            mime:EntityError err => io:println("Error in getting string payload");
            string textContent => io:println(textContent);
        }
    }
}

Decode Nested BodyParts in Multipart

Ballerina supports decoding of nested parts within a multipart entity upto any level.

import ballerina/http;
import ballerina/mime;
import ballerina/io;
endpoint http:Listener multipartEP {
    port:9090
};
@http:ServiceConfig {basePath:"/nestedparts"}
service<http:Service> test bind multipartEP {
    @http:ResourceConfig {
      methods:["POST"],
      path:"/decoder"
    }
    nestedPartReceiver (endpoint conn, http:Request req)  {
        http:Response res = new;
        match req.getMultiparts() {
            mime:EntityError err => {
                res.setStringPayload("Error occurred while decoding parent parts!");
                res.statusCode = 500;
            }
            mime:Entity[] parentParts => {
                int i = 0;
                while (i < lengthof parentParts) {
                    mime:Entity parentPart = parentParts[i];
                    handleNestedParts(parentPart);
                    i = i + 1;
                }
                res.setStringPayload("Nested Parts Received!");
            }
        }
        _ = conn -> respond(res);
    }
}
function handleNestedParts (mime:Entity parentPart) {
    string contentTypeOfParent = parentPart.contentType.toString();
    if (contentTypeOfParent.hasPrefix("multipart/")) {
        match parentPart.getBodyParts() {
            mime:EntityError err => {
                io:println("Error retrieving child parts!");
            }
            mime:Entity[] childParts => {
            int i = 0;
            io:println("Nested Parts Detected!");
                while (i < lengthof childParts) {
                    mime:Entity childPart = childParts[i];
                    handleContent(childPart);
                    i = i + 1;
                }
            }
        }
    }
}

Given a parent part, get it’s child parts.

function handleContent (mime:Entity bodyPart) {
    string contentType = bodyPart.contentType.toString();
    if (mime:APPLICATION_XML == contentType || mime:TEXT_XML == contentType) {

Handling body part content logic varies according to user’s requirement..

        var payload = bodyPart.getXml();
        match payload {
            mime:EntityError err => io:println("Error in getting xml payload");
            xml xmlContent => io:println(xmlContent);
        }
    } else if (mime:APPLICATION_JSON == contentType) {

Extract xml data from body part and print.

        var payload = bodyPart.getJson();
        match payload {
            mime:EntityError err => io:println("Error in getting json payload");
            json jsonContent => io:println(jsonContent);
        }
    } else if (mime:TEXT_PLAIN == contentType) {

Extract json data from body part and print.

        var payload = bodyPart.getText();
        match payload {
            mime:EntityError err => io:println("Error in getting string payload");
            string textContent => io:println(textContent);
        }
    }
}

Extract text data from body part and print.

$ ballerina run decode-nested-bodyparts-in-multipart.bal