Axis2/C supports MTOM (SOAP Message Transmission Optimization Mechanism) and SwA (SOAP with attachments) that allows you to easily implement clients and services to handle attachments either way. In addition, you can convert binary content to base64 and vice-versa while sending and receiving attachments. This tutorial discusses the API and configuration options for handling SOAP Attachments within Axis2/C.
Applies To
| Apache Axis2/C [1] | 1.4.0 and above |
| Environment | Linux , Windows |
Table of Contents
- Axis2/C Configurations for Attachments [1]
- axiom_data_handler and axiom_text API [1]
- Summary [1]
- References and Useful Links [1]
Binary content goes here
1. A SOAP message with a binary attachment
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<ns1:mtomSample xmlns:ns1="http://ws.apache.org/axis2/c/samples/mtom">
<ns1:fileName>test.jpg</ns1:fileName>
<ns1:image>/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAgADwDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD2PRvC+m6LI10iPdalKMT6hdHzLiX6seg/2Vwo7CsnU/id4W0jxZB4cvNQCXknDyAZihY9Fdv4Sf074qt8VPG7eC/CpazIOr3zeRZJjJDd3x/sg/mVrldG+BWmT+CJoddaR/EV8PPlvS5ZreU5IUc/MBn5v7xzz0wAex1zfjfxnZeBdDj1W/tbm4he4WDbbhSwJViCckcfLj8RXH/CHxRqBa/8D+ICf7Y0QlEZj/rYQQo+uMjB7qy12Hj3wqnjLwbf6NuCTSKHt5D0WVTlc+x6H2JoA3LYW0+2/hVS1xEn70DlkGSoz6DcfzNWK8X+HXxRtdEsU8I+NC2lanpmLZJJ1wjovCgkcAgYGehGDmuk8V/GXwp4f0yV7HUbfVb8r+5t7V96lu25xwB6859qANrTPHmnar461Lwnb29z9ssIzJLMQvlHG0EAg5zlwOnY1t6XrFvqs2pRQLIrafdm0l3gAFwiPkc9MOP1rz34OeE9S0611HxR4gRhrOtyeayuuHjjJLcj+EsTnHYBenSun8Ff8hHxh/2Hn/8ASeCgDz3Ulbxh+0naafMBLY6BbiYx5+UMFDbvrveMH/dFehXPhG8n+Itn4oXX7uO1t7cwtpoH7t8hhnOcYyQcYJyo56Yx/B3gLUtA+IPibxJqF1azJqkj/Z1jLF0QybgGyAOgUcZ6V6FQB4l8TAvhD4v+FPF6MEhum+zXePRcKzH1+ST/AMcr1nxHr1n4Y8PXus3zYgtYy5APLnoqj3JIA+tcp8VvAd9480WwtdOuLWC4tbnzS9wWA27SCBtB5zj8qn+JvhDVfGng2HRtNuraCf7RHJM1wzBWVVbj5QTncVPTtQB5rofgTWfjHdHxZ4uvpbLTpMpZW1soDmME9CRhV9yCW5PTGb+t/AMaPCuq+C9XvV1WzImiiumRt7DnCsFGD9QQehx1r2jS7CLStJs9PgXbDawJCg9lUAfyq3QBwvwt8eN448PSG9jEWr2DiG9jAxk84cDtnB47EGr/AIK/5CPjD/sPP/6TwVk+GvAWoaB8Udf8SLc239l6ojEW6M28SFlYswxjqH7/AMVdR4f0abSbrXJZZI3Goak15GEz8qmKNMH3yh/MUAf/2Q==</ns1:image>
</ns1:mtomSample>
</soapenv:Body></soapenv:Envelope>
2. A SOAP message with base64 encoded text in its payload
One of the issues in using enableMTOM parameter to true in axis2.xml is that it causes MIME headers to be sent with the SOAP message, whether or not you are sending attachments. This may not be the desired behavior for your other clients and services. Therefore, it is always better to set enableMTOM programatically instead of using the axis2.xml parameter.
[2]axiom_data_handler and axiom_text API
Data Handler is the structure that represents the attachments and it provides functions for sending and receiving attachments in axiom. It is attached to a text node in axiom tree.
You can create a data handler by providing the path of the attachment file and the MIME type. Then, it should be attached to an axiom text element.
image_om_ele = axiom_element_create(env, mtom_om_node, "image", ns1, &image_om_node);
data_handler = axiom_data_handler_create(env, "axis2.jpg", "image/jpeg");
data_text = axiom_text_create_with_data_handler(env, image_om_node, data_handler, &text_om_node);
Of course you can create the data handler without specifying the file name and MIME type and then later set them in. This is specially useful when you already have your attachment contents in memory.
data_handler = axiom_data_handler_create(env, NULL, NULL);
axiom_data_handler_set_binary_data(data_handler, env, buffer, buffer_len);
axiom_data_handler_set_content_type(data_handler, env,"image/jpeg");
axiom_text_create_with_data_handler(env, mtom_om_node, data_handler, &text_node);
You can set whether the attachment should be sent in optimized or non optimized format on the axiom text, which contains the data handler. However, if you have enableMTOM option set to false, the attachment will be sent in base64 format, irrespective of this option.
data_text = axiom_text_create_with_data_handler(env, image_om_node, data_handler, &data_om_node);
axiom_text_set_optimize(data_text, env, AXIS2_TRUE);
When receiving attachments, you can either save the attachment to a file or you can obtain it as a buffer with the buffer length.
axiom_data_handler_set_file_name(data_handler, env, text_str); axiom_data_handler_write_to(data_handler, env);
buffer = axiom_data_handler_get_input_stream(data_handler, env); buffer_len = axiom_data_handler_get_input_stream_len(data_handler, env); mime_type = axiom_data_handler_get_content_type(data_handler, env);
In receiving attachments, knowing the exact location of the binary attachment allows you to easily obtain axiom text and the data handler. However, if the location is unknown, you will have to iterate through the axiom tree, looking for axiom text containing data handlers.
There is an easier way to access the attachments received. axiom_soap_builder object contains a hash table with content id (cid ) as the key and data_handler as the value. Content id is the value of the href attribute except "cid:". This uniquely identifies attachments received within a SOAP message.
<xop:Include href="cid:1.fea3613d-9541-4749-a558-b984a55a92f6@apache.org" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
soap_builder = axiom_soap_envelope_get_soap_builder(soap_envelope, env); mime_body_parts = axiom_soap_builder_get_mime_body_parts(soap_builder, env);
By iterating through the hash table, you are able to obtain all attachments received. This technique can be used in the event of receiving attachments in SwA format as well.
if(mime_body_parts) {
axutil_hash_index_t *hi = NULL;
axis2_char_t *cid = NULL;
axiom_data_handler_t *data_handler = NULL;
for (hi = axutil_hash_first(mime_body_parts, env);
hi; hi = axutil_hash_next(env, hi))
{
axutil_hash_this(hi, (const void **)&cid, NULL, (void**)&data_handler);
if(cid && data_handler)
{
char *mime_type = NULL;
char *data = NULL;
int data_len = 0;
axiom_data_handler_read_from (data_handler, env, &data, &data_len);
mime_type = axiom_data_handler_get_content_type(data_handler, env);
/** Use the attachment content here */
}
}
}
You can send attachments using the SwA format by setting swa option in axiom text containing the data handler. Note the absence of xop:include element.
data_text = axiom_text_create_with_data_handler(env, image_om_node, data_handler, &data_om_node);
axiom_text_set_is_swa(data_text, env, AXIS2_TRUE);
--MIMEBoundary09b42e84-c3d9-4d9e-b80b-91f834edc878
content-transfer-encoding: binary
content-id: <0.d9b487fa-22a2-4d63-b8c2-9a91ee4b4dc2@apache.org>content-type: application/xop+xml;charset=UTF-8;type="text/xml";
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<ns1:mtomSample xmlns:ns1="http://ws.apache.org/axis2/c/samples/mtom">
<ns1:fileName>test.jpg</ns1:fileName>
<ns1:image>1.9f4dc218-ca93-46f7-86b2-129500358e23@apache.org</ns1:image>
</ns1:mtomSample>
</soapenv:Body>
</soapenv:Envelope>--MIMEBoundary09b42e84-c3d9-4d9e-b80b-91f834edc878content-transfer-encoding: binarycontent-id:
<1.9f4dc218-ca93-46f7-86b2-129500358e23@apache.org>content-type: image/jpeg
Binary content goes here
Now you know all necessary detials on how to use Axis2/C to send and receive attachments.
Axis2/C manual [3]
Author
Nandika Jayawardana is a senior software engineer at wso2. nandika at wso2.com