Welcome!

AJAX & REA Authors: John Funnell, Bob Little, Kevin Hoffman, Maureen O'Gara, Onkar Singh

Related Topics: Adobe Flex, ColdFusion, AJAX & REA

Adobe Flex: Article

Binary Data, ColdFusion & Flex

Sending BitmapData to a server and saving it as a JPG file

If you aren't using remoting, you can save the data using Web Services or HTTP services. Most seasoned ColdFusion developers might stop me here and say... "If you're using CFCs as Web Services, why wouldn't you just use them as RemoteObject methods since they are faster?" My response is this: This is just an example. You may be able to take this method and apply it to other technologies where it may be applicable (.NET, Java, PHP, etc.).

<cfcomponent name="ImageSave" displayname="ImageSave" output="false">
    <cffunction name="WSsave" access="remote" output="false" returntype="void">
       <cfargument name="data" type="string" required="true" />
       <cffile action="write" file="c:\temp\ws_data.jpg"
output="#ToBinary(arguments.data)#" />
    </cffunction>
</cfcomponent>

You can see that the code for the Web Service method is very similar to the previous example. The only difference is that the toBinary method is being used to convert the data from a Base64-encoded string into binary data. The CFC's WSsave (Web Service save) method is expecting a Base64-encoded string as a parameter. When executed, the data is also written to the file system using the <CFFILE /> "write" method.

In Flex, we need an instance of a mx:WebService to save the data:

<mx:WebService
id="ws"
    showBusyCursor="true"
    wsdl="/BinaryData/cf/ImageSave.cfc?wsdl">

<mx:operation name="WSsave"
result="onResult('Data Saved via mx:WebService')"
fault="onFault(event)" />
</mx:WebService>

To save the data, we first need to Base64-encode it. The following function will take care of that for us:

private function base64Encode( data : ByteArray ) : String
{
var encoder : Base64Encoder = new Base64Encoder();
    encoder.encodeBytes( data );
    return encoder.flush();
}

We'll then invoke the WSsave method and pass the Base64-encoded ByteArray as a parameter:

var bd : BitmapData = getUIComponentBitmapData( paintCanvas );
var encoder : JPEGEncoder = new JPEGEncoder(75);
var data : ByteArray = encoder.encode( bd );
ws.WSsave( base64Encode( data ) );

If you want to save the binary data without using RemoteObjects or Web Services, you can always use a standard HTTP post method. In Flex, you'll have to create an instance of an HTTPService object, with the method set to "POST":

<mx:HTTPService
id="hs"
    showBusyCursor="true"
    useProxy="false"
    method="POST"
    resultFormat="text"
    url="/BinaryData/cf/HTTPImageSave.cfm"
result="onResult('Data Saved via mx:HTTPService')"
fault="onFault(event)" />

The file HTTPImageSave.cfm is actually very simple. The save occurs with only two lines of code:

<cfparam name="data" type="string" default="">
<cffile action="write" file="c:\temp\http_data.jpg" output="#ToBinary( data )#" />

You'll notice in this case that the data is also being written to the file system using the toBinary method (to convert the Base64-encoded string back into binary data). When invoking the HTTPService, you'll have to create an object containing the parameters for the HTTPService and send it as the parameter of the HTTPService.send method (note "hs" is the id of the HTTPService instance):

var bd : BitmapData = getUIComponentBitmapData( paintCanvas );
var encoder : JPEGEncoder = new JPEGEncoder(75);
var data : ByteArray = encoder.encode( bd );
var params : Object = { data : base64Encode( data ) };
hs.send( params );

...and that is how you save binary image data using RemoteObjects, Web Services, or HTTPServices. This doesn't just apply to images. This applies to any kind of binary data; the only difference is that the image data first gets encoded to a JPG ByteArray. The AS3 corelib project on Adobe Labs/Google Code also includes class libraries that enable you to save data as PNG images instead of JPG images, so JPG isn't your only option.

A few things to keep in mind for real-world applications... It's best practice to use <CFFILE /> in a <CFTRY/> statement to catch any file system errors that may occur (not enough space, permissions, etc.). It's also best practice to use <CFLOCK /> with <CFFILE /> to prevent any errors due to data synchronization, threading access, or deadlock scenarios.

A working example and the source code from this article can be viewed online at www.cynergysystems.com/blogs/blogs/andrew.trice/binary_data_example/ or downloaded from www.cynergysystems.com/blogs/blogs/andrew.trice/binary_data_example/BinaryData.zip.

More Stories By Andrew Trice

Andrew Trice is a consultant with Cynergy Systems in Washington, DC, where he specializes in development of Flex-based Rich Internet Applications. Andrew has over 5 years of proven experience in the RIA industry, including application design and development using Flex, Flash, ColdFusion, J2EE and .NET architectures.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.