Search code examples
javahttpapache-camelmultipartform-data

Get key-value pairs from multipart/form-data HTTP POST request in Camel


I have an endpoint setup using Apache Camel to receive a multipart/form-data HTTP request. Essentially I am trying to submit a data file and a configuration file for processing. The request is as follows (generated by Postman):

POST /upload HTTP/1.1
Host: localhost:8900
Content-Length: 363
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="data"; filename="data-file.json"
Content-Type: application/json

(data)
----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="config"; filename="config-file.json"
Content-Type: application/json

(data)
----WebKitFormBoundary7MA4YWxkTrZu0gW

My route is set up like so:

@Component
public class FileReceiverRoute extends RouteBuilder {

    @Override
    public void configure() throws Exception {

        rest()
                .post("/upload")
                .consumes(MediaType.MULTIPART_FORM_DATA_VALUE)
                .bindingMode(RestBindingMode.off)
                .route().routeId("upload-route")
                .unmarshal().mimeMultipart()
                .setHeader(Exchange.FILE_NAME, () -> UUID.randomUUID().toString())
                .to("file:{{temp.input.files.dir}}")
                .process(configFileProcessor)
                // on to further processing
    }
}

And my config file processor:

@Component
public class ConfigFileProcessor implements Processor {

    @Override
    public void process(Exchange exchange) throws Exception {
        Message message = exchange.getIn();
        AttachmentMessage attachmentMessage = exchange.getMessage(AttachmentMessage.class);
        Map<String, Attachment> attachmentObjects = attachmentMessage.getAttachmentObjects();

        // this fails - the key is instead the file name "config-file.json"
        Attachment configAttachment = attachmentObjects.get("config");
    }
}

I want to be able to retrieve the key-value pairs from the form-data and process the data and config files accordingly. Instead I get the following behaviour:

  • The first value in the form (in this case data-file.json) is parsed into the Camel message body, and the key seems to be discarded. The rest of the entries are parsed into an AttachmentMessage. This behaviour is documented here https://stackoverflow.com/a/67566273/11248602
  • The keys in the AttachmentMessage are not the original keys from the form-data request, but the filenames (e.g. config-file.json)

Is there any way to parse this request into a map or similar structure so that all the original keys and values can be accessed?


Solution

  • For the sake of clarity, as the proposed solution here above seems to work, a bit more explanations (although it is more a workaround than a solution):

    Starting from:

    Map<String, Attachment> attachmentObjects = attachmentMessage.getAttachmentObjects();
    

    It is possible to browse all map entries, and for each found Attachment object, examine the attachment headers using getHeaderNames(), among other the 'Content-Disposition' one:

    Content-Disposition: form-data; name="data"; filename="data-file.json"
    

    which can finally be parsed to grab the form name ('data' in this example).

    Not straightforward true, but this apparently works...