This was sort of based on an Ask Ben inquiry, so I will include it in this section, but it's not entirely accurate. Someone had asked me about passing a file to a web service and I had suggested that one of the ways to do this was to pass it using a Base64 encoding of the binary data. This would allow the data to be easily defined using XML, which is how many web services function (think SOAP, think XML-RPC). While I am not following SOAP or XML-RPC standards in this quick demo, the ideas stay the same.
There are two players in this game. One entity is the file that reads the file data, encodes it, and submits it to the web service. The other entity is the actual web service file that accepts the data, converts the encoded data back to binary, and writes it to a file.
To demo this, we are going to first read in a JPG file and then post it as XML data using the ColdFusion's CFHttp and CFHttpParam tags:
Launch code in new window » Download code as text file »
As you can see, when I store the data in the XML string, I am being very careful not to include anything that is NOT XML safe. I am, however, not encoding the Base64 data. That makes me nervous, but I feel like 95% sure that Base64 is inherently XML safe since the Base64 data type is part of the XML-RPC standard as well as the XStandard web services SOAP definition. Once we have our XML string, we are simply posting it to the target URL using the CFHttpParam tag of type XML. Using this tag, the CFHttp request automatically sets the content to be of type text/xml and defines our XML string as the request data content.
Now, on the other side of the submission, we have our web service, which takes the XML post, extracts the Base64 data, converts it back to Binary, and writes it to the file system:
Launch code in new window » Download code as text file »
I have not included any real error handling or fail handlers as this is just a demo in a controlled environment. If this were a real web service, I am sure you'd want to have CFTry / CFCatch blocks as well as a return value to indicate success or error messages. A lot of that depends on the type of standards you are using (ex. XML-RPC has a very defined way to return errors).
There's not a whole lot going on here. Really, it's just about knowing how to use and leverage ColdFusion's ToBase64() and ToBinary() methods. If you want to see any more of this, my ColdFusion XStandard Web Services project provides file uploading using a SOAP version of this idea.
Download Code Snippet ZIP File
Comments (6) | Post Comment | Ask Ben | Permalink | Other Searches | Print Page
As always Ben you don't disappoint. Thanks for the info on these functions.
Posted by Paul Roe on Jan 4, 2008 at 11:20 AM
@Paul,
My pleasure! Let me know if you have any follow-up questions.
Posted by Ben Nadel on Jan 4, 2008 at 11:23 AM
As a suggestion, you may want to wrap the base64 encoded data in a CDATA block since it's being transmitted in an XML format. Base64 is a great encoding for passing data around over HTTP, but to avoid the stress of the XML parser getting its hands on your data, a CDATA block is always useful.
BTW - Thanks for a great site. I refer a lot of people using CF to your site for advice and tutorials. Keep up the great work!
Posted by Brian LeGros on Jan 4, 2008 at 11:25 AM
@Brian,
Good suggestion, thanks. And also, thanks for the kind words about the blog :)
Posted by Ben Nadel on Jan 4, 2008 at 11:53 AM
Base64 uses A-Z a-z 0-9 + / and =. There's nothing in there that could invalidate the XML. So yes, you could use CDATA blocks, but it's not needed.
Hopefully that gives you the other 5% Ben. :)
http://en.wikipedia.org/wiki/Base64
Posted by Elliott Sprehn on Jan 4, 2008 at 1:45 PM
@Elliott,
Perfect! Thanks. I kept trying to find the definition, but all I ever found was that it uses "printable characters", which did not instill 100% confidence.
Posted by Ben Nadel on Jan 4, 2008 at 1:46 PM