English 中文(简体)
Apache Camel multipart HTTP post (file upload)
原标题:

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

最佳回答

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")
问题回答

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.

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.

You can do it in programmatically process

routes:

from("jetty:{{camel.address}}/" + method)
    .process(ex -> SomeClassProcessing.ProcessMultipart(ex));

processing:

public class SomeClassProcessing {
public static void ProcessMultipart(Exchange exchange) {
    AttachmentMessage attIn = exchange.getIn(AttachmentMessage.class);
    Map<String, DataHandler> atts = attIn.getAttachments();
    
    for (var pair: atts.entrySet()) {
        var fileName = pair.getKey();
        var att = pair.getValue();
        
        var is = att.getInputStream();
        var fileContent = new byte[is.available()];
        is.read(fileContent);
    
        // Now file content is in array of byte
    }
}




相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签