Filippos Georgiou
Filippos Georgiou

Reputation: 53

Spring Camel Rest route problem with file upload

I've been struggling for the past 2 days with the following issue. I'm trying to upload a csv file via a POST route. The file gets picked for upload from an html form.

<form method="POST" action="uploadFile" enctype="multipart/form-data">
    <div>
        <div style="display:inline;">
            <label path="file">Select a file to upload</label>
        </div>
        <div style="display:inline;">
            <input type="file" name="file" />
        </div>
    </div>
    <div>
        <input type="submit" value="Submit" />
    </div>
</form>

This is the camel POST route:

rest(properties.getRestEndpointPrefix() + properties.getRestEndpointUploadFileUrl())
    .post()
    .consumes(MediaType.MULTIPART_FORM_DATA_VALUE)
    .route()
    .routeId("postUploadForm")
    .process((exchange) -> {
        InputStream is = exchange.getIn().getBody(InputStream.class);
        Map<String, String> body = exchange.getIn().getBody(Map.class);
        MimeBodyPart mimeMessage = new MimeBodyPart(is);
        DataHandler dh = mimeMessage.getDataHandler();
        exchange.getIn().setBody(dh.getInputStream());
        exchange.getIn().setHeader(Exchange.FILE_NAME, dh.getName());
    })
    .to(properties.getIncomingUri());

The only solution that actually worked for me was Bedla's from this post,using MimeBodyPart. For some reason whenever I tried to use spring's MultiPart and children it was always null when reaching out to the camel body, whixh i presume is because I don't/can't use the @RequestPart annotation.

My issue is that the existing parsing retains the multipart/form-data boundary at the end of the file, breaking any subsequent csv parsing that takes place. Below is the boundary, generated by postman.

----------------------------521923768224522097053873--

Any help is appreciated, Thanks a lot in advance!

[EDIT]

Using @karine 's solution, I did get thr clean body and kept beforehand the file name. Final rest route below:

rest(properties.getRestEndpointPrefix() + properties.getRestEndpointUploadFileUrl())
    .post()
    .consumes(MediaType.MULTIPART_FORM_DATA_VALUE)
    .route()
    .routeId("postUploadForm")
    .process((exchange) -> {
        //Keep the file name from the unmarshalled file. After unmarshalling, fileName will be lost
        MimeBodyPart mimeMessage = new MimeBodyPart(exchange.getIn().getBody(InputStream.class));
        exchange.getIn().setHeader(Exchange.FILE_NAME, mimeMessage.getDataHandler().getName());
    })
    .unmarshal()
    .mimeMultipart()
    .to(properties.getIncomingUri());

Upvotes: 0

Views: 661

Answers (2)

karine
karine

Reputation: 38

Here is the way that I retrieve the content of an upload file

    ...
    .post()
     .bindingMode(RestBindingMode.off)
     .route()
        .routeId("postUploadForm")
        .unmarshal().mimeMultipart()
        .process((exchange) -> {
            InputStream is = exchange.getIn().getBody(InputStream.class);
            // is contains the content file
            ...
        })

But with this way, I cannot get the file name. I hope it can help a little bit

Upvotes: 1

Demobilizer
Demobilizer

Reputation: 748

you may try by replacing your .process method with following!

    .process(exchange -> {
        String strMessage = FileUtils.readFileToString(
                new File(yourFileName), StandardCharsets.UTF_8);
        exchange.getMessage().setBody(strMessage);
        exchange.getMessage().setHeader(Exchange.FILE_NAME, yourFileName);
    })

Upvotes: 0

Related Questions