Question

How can I do multipart file uploads using the Apache Camel HTTP component ?

Was it helpful?

Solution

I don't know is it possible to send multipart forms using the HTTP component.

If you need the workaround, you can create POJO Spring Bean that uses the Apache Http Client (and its MultipartPostMethod). Then you can route your message to that bean:

from("activemq:uploadQueue").to("bean:myApacheHttpClientBean?method=sendMultiPart")

OTHER TIPS

As long as your message body is in multipart/form-data format, you can use the Camel http component to POST it to another server. The trick is to set your Content-Type properly and set the request method to be POST:

<route>
  <from uri="direct:start"/>
  <setBody>
    <![CDATA[
    --__MyCoolBoundary__
    Content-Disposition: form-data; name="name"

    Paul Mietz Egli
    --__MyCoolBoundary__
    Content-Disposition: form-data; name="email"

    paul@example.com
    --__MyCoolBoundary__--
    ]]>
  </setBody>
  <setHeader headerName="Content-Type">
    <constant>multipart/form-data; boundary="__MyCoolBoundary__"</constant>
  </setHeader>
  <setHeader headerName="CamelHttpMethod">
    <constant>POST</constant>
  </setHeader>
  <to uri="http://www.example.com/mywebservice.php"/>
</route>

Obviously, the example body above isn't that useful because it's all static data. There are a number of ways you can construct the body -- I've used XSLT outputting in text mode, a scripted expression (e.g. <groovy>...</groovy>), and a Spring bean. XSLT works well when your incoming message body is already an XML document:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
--__MyCoolBoundary__
Content-Disposition: form-data; name="name"

<xsl:value-of select="//name"/>
--__MyCoolBoundary__--
</xsl:stylesheet>

You do need to be careful about extra whitespace, however. Hope this helps!

I had working on a web project by below features:

  1. Login Form: people login and can upload the file; (Camel: Jetty, Http, JDBC)

  2. Upload Form; upload servlet: if people can login; can upload xml file to ftp or web server; (Camel: file)

3.File is validated by my .xsd file; (Camel: Validator)

  1. File is checked by my .xsl schema file; (Camel: XSLT)

I was create web project by my favorite IDE (IntelliJ IDEA by Jetbrains); I describe part of my scenario with source code and hope this is useful ☺

1) index.html

<form action="http://0.0.0.0:8080/hello" method="post">

<fieldset title="Login" >

    username:<input type="text" id="user" name="user"/>
    password:<input type="password" id="pass" name="pass" />

    <input type="submit" id="submit" value="submit"/>

</fieldset>

First you have to create database and login table; then add some sample data; for example add these files:

2) schema.sql

DROP TABLE IF EXISTS CONTACT;
CREATE TABLE CONTACT (
   ID INT NOT NULL AUTO_INCREMENT
 , NAME VARCHAR(40) NOT NULL
 , USERNAME VARCHAR(40) NOT NULL
 , PASSWORD VARCHAR(60) NOT NULL
 , VERSION INT NOT NULL DEFAULT 0
 , UNIQUE UQ_CONTACT_1 (USERNAME)
 , PRIMARY KEY (ID));

3) test-data.sql

insert into contact (name, username, password) values ('ali', 'aliti', '123');
insert into contact (name, username, password) values ('shahab', 'shahab', '147');
insert into contact (name, username, password) values ('farhad', 'farhad', '159');

4) config spring-context.xml

Then, you can use embedded databases like derby, H2, mysql or others. Add below config to your spring config file:

<jdbc:embedded-database id="dataSource" type="H2">
    <jdbc:script location="classpath:schema.sql"/>
    <jdbc:script location="classpath:test-data.sql"/>
</jdbc:embedded-database>

5) camel-context.xml

Now, you can run your project; before do that you have to add this route to your camel context:

<route>
        <from uri="jetty:http://0.0.0.0:8080/hello"/>

        <setBody>
            <simple>
                select * from contact where USERNAME = '${in.header.user}' and PASSWORD = '${in.header.pass}'
            </simple>
        </setBody>

        <to uri="jdbc:dataSource"/>

        <process ref="loginProcessor"/>

        <log message=">>>header: ${in.header.name}"/>

        <choice>
            <when>
                <simple>${in.header.name} == null</simple>
                <to uri="jetty://http://localhost:9090/fail.html?bridgeEndpoint=true"/>
            </when>

            <otherwise>
                <to uri="jetty://http://localhost:9090/file.html?bridgeEndpoint=true"/>
            </otherwise>
        </choice>

When you run our project; index.html page was shown and you can put the username and password text boxes and send your form.

Actually Camel was listening to this jetty port and got your post information. You can get these information by Camel’s header like '${in.header.user}'.

As you can see, I set my select query in Camel’s Body, Thus the select result is also store in Camel’s Body. I want to read my result and got some decisions, for this reason I add Camel processor as below:

6) LoginProcessor.java

public class LoginProcessor implements Processor {
public void process(Exchange exchange) throws Exception {

    int size = ((ArrayList) exchange.getIn().getBody()).size();
    if (size > 0) {
        Object name = ((LinkedHashMap) (((ArrayList) exchange.getIn().getBody()).get(0))).get("NAME");
        System.out.println("welcome user: " + name);
        exchange.getOut().setHeader("name",name);
    } else {
        System.out.println("user or pass are invalid. ");
        exchange.getOut().setHeader("name",null);
    }
}

}

In LoginProcessor I checked the body and if input username and password are valid; Add Camel’s header property and named by ‘name’ by field name of table. Otherwise set null value in Camel’s header property.

Back to Camel context xml file and continue the route. If Camel’s header is null; redirect user to fail.html page; otherwise redirect to page that get file from user(file.html).

Note: bridgeEndpoint property You are setting the http endpoint to be bridgeEndpoint which means the request url will be updated with request URI.

Does it have to be using Camel?

Apache Fileupload does this quite simply http://commons.apache.org/fileupload/using.html

Could you please provide more details how do you want multipart form reach apache camel?

Should it be some form on a webpage that send directly to Camel route? Or AMQ queue? I'd suggest you checking Apache HTTP and Apache Jetty components.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top