Converting A Base64 Value Back Into A String Using ColdFusion

Posted September 5, 2008 at 2:54 PM by Ben Nadel

Tags: ColdFusion

This might seem super obvious to some of you, but this small problem had me stumped for a good 10 minutes this morning. I had an XML value that I was converting to Base64 for an HTTP post. Then, on the other side, I needed to take that Base64 encoded value and convert it back to a regular string for use with XML parsing. And then it hit, I had no idea how to, in ColdFusion, take a Base64 encoded value and convert it back to the original string.

Once I figured it out, it was laughably simple:

  • <!--- Create a string value. --->
  • <cfset strValue = "Hey there cutie patootie." />
  •  
  • <!--- Convert to base 64. --->
  • <cfset strBase64Value = ToBase64( strValue ) />
  •  
  • <!---
  • To convert the base 64 value back to string, simply convert
  • the it a binary representation and then back into to a string.
  • --->
  • <cfset strNewValue = ToString( ToBinary( strBase64Value ) ) />
  •  
  • <!--- Output test data. --->
  • <p>
  • <cfoutput>
  • Base 64: #strBase64Value#<br />
  • Value: #strNewValue#
  • </cfoutput>
  • </p>

Running the above code, we get the following output:

Base 64: SGV5IHRoZXJlIGN1dGllIHBhdG9vdGllLg==
Value: Hey there cutie patootie.

In ColdFusion, the ToBinary() function takes a Base64 encoded value and converts it to its binary representation. This, of course, is a Byte Array. In our example, where each character of a string is represented by a single byte, we have one character per byte array index. Then, calling ToString() on that Byte Array simply converts that character-based byte array back into its string representation.



Reader Comments

Sep 5, 2008 at 3:11 PM // reply »
12 Comments

I've done something similar in a MS SQL Server database - take a text field and output as string:

CAST(CAST(textField AS VARBINARY(1000)) AS VARCHAR(1000))

I think that's how it worked. I'm fairly sure most DBMSs have similar functions.


Sep 5, 2008 at 3:42 PM // reply »
8 Comments

Earlier this week, I had to do the same thing except that the strValue was a GUID (hex). I found that converting the GUID to decimal and then trying to run ToBase64 on the resulting HUGE number resulted in a CF error. Apparently ToBase64 can only handle decimals up to a certain size. I did find the solution though (with Ray's help) and posted it here: http://www.coldfusionjedi.com/forums/messages.cfm?threadid=2E1AFB13-19B9-E658-9DEC415EB6931B97

Enjoy!


Sep 5, 2008 at 4:04 PM // reply »
6 Comments

Just FYI Ben. The CFML Reference manual is your friend. It's on page 1228.


Sep 5, 2008 at 4:24 PM // reply »
10,638 Comments

@Matt,

Good to know.

@John,

I assume you needed to go to a decimal first for some reason; otherwise, you can convert any string to Base64 regardless of length.

@Gary,

It's funny, I have gone from String -> Base64 -> Binary so many times that I totally blanked on going the reverse order.

ps. I love the CFML Reference guide :)


Sep 5, 2008 at 4:52 PM // reply »
8 Comments

@Ben,

Yes. Per my post on coldfusionjedi.com, I needed a *shorter* version of the GUID. If you treat it as a (hex) number, the resulting Base64 has fewer characters/digits than the original:

GUID: e1c4c2926-b394-6808-e611-f95a4c41cbf
Base64: 4cTCkms5RoCOYR+VpMQcvw==

If you treat the GUID as a string, the resulting Base64 has more characters/digits than the original:

GUID: e1c4c2926-b394-6808-e611-f95a4c41cbf
Base64: ZTFjNGMyOTI2YjM5NDY4MDhlNjExZjk1YTRjNDFjYmY=

Make sense?

I discovered this phenomenon on Wikipedia, of all places, "When printing fewer characters is desired, GUIDs are sometimes encoded into a base64 or Ascii85 string. Base64-encoded GUID consists of 22 to 24 characters (depending on padding)."

http://en.wikipedia.org/wiki/GUID


Sep 5, 2008 at 4:56 PM // reply »
10,638 Comments

@John,

Ahh, yes, that makes sense. Thanks for the clarification.


Apr 26, 2011 at 5:53 PM // reply »
4 Comments

@John, thanks the hex tip. One thing I've found is the GUIDs are coming back with some 0's missing. Did you notice this?

GUID before: 3D0F1C1C-E3F6-11D3-896A-00105A7027AA

"GUID" after: 3DF1C1CE-3F61-1D38-96A0-105A7027AA


Apr 26, 2011 at 6:09 PM // reply »
8 Comments

@Jason No, I either didn't notice that or didn't have that problem and, since Sep 2008, my need for this bit of logic went away and the code in question is not easily accessible. Perhaps you can share your code?


Apr 26, 2011 at 6:11 PM // reply »
4 Comments

@John, It's your original code, I copy/pasted and used it for testing. No biggie, just wondering if it did the same for you. Thx


Apr 26, 2011 at 6:15 PM // reply »
8 Comments

@Jason My bad. Right there it is at http://www.coldfusionjedi.com/forums/messages.cfm?threadid=2E1AFB13-19B9-E658-9DEC415EB6931B97 No, I didn't notice what you're describing. I was using ACF8. You?


Apr 26, 2011 at 6:30 PM // reply »
4 Comments

@John, should be the same as yours unless my CF default is somehow different.


Apr 26, 2011 at 6:40 PM // reply »
8 Comments

@Jason Try these and let me know. I think I might have fixed it and forgotten to update post on Ray's site. If this works, let me know and I will...

<cffunction access="public" name="HexToBase64" output="yes" returntype="string">
<cfargument name="Hex" type="string" required="yes">
<cfset Hex = Replace(Hex, "-", "", "ALL")>
<cfset outStream = CreateObject("java", "java.io.ByteArrayOutputStream").init()>
<cfset inputLength = Len(Hex)>
<cfset outputString = "">
<cfset i = 0>
<cfset ch = "">
<cfif inputLength mod 2 neq 0>
<cfset Hex = "0" & Hex>
</cfif>
<cfloop from="1" to="#inputLength#" index="i" step="2">
<cfset ch = Mid(Hex, i, 2)>
<cfset outStream.write(javacast("int", InputBaseN(ch, 16)))>
</cfloop>
<cfset outStream.flush()>
<cfset outStream.close()>
<cfreturn ToBase64(outStream.toByteArray())>
</cffunction>

<cffunction access="public" name="Base64ToHex" output="yes" returntype="string">
<cfargument name="Base64" type="string" required="yes">
<cfset aBinary = ToBinary(Base64)>
<cfset Hex = "">
<cfloop index="i" from="1" to="#ArrayLen(aBinary)#">
<cfset Hex = Hex & Replace(RJustify(FormatBaseN(BitAnd(aBinary[i], 255), 16), 2), " ", "0", "ALL")>
</cfloop>
<cfset Hex = Insert("-", Hex, 20)>
<cfset Hex = Insert("-", Hex, 16)>
<cfset Hex = Insert("-", Hex, 12)>
<cfset Hex = Insert("-", Hex, 8)>
<cfreturn Hex>
</cffunction>


Apr 27, 2011 at 11:54 AM // reply »
4 Comments

@John, that worked, thanks for the update!


Apr 27, 2011 at 11:56 AM // reply »
8 Comments

@Jason You're welcome!



Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
Feb 3, 2012 at 10:49 PM
How I Got Node.js Running On A Linux Micro Instance Using Amazon EC2
Wow this was really helpful! Only thing I would add is you need to update your .bash_profile after you edit the secure_path. This is what I did: $ . ~/.bash_profile Otherwise, NPM won't be found. ... read »
Feb 3, 2012 at 10:14 PM
Pushing Base64-Encoded Images Over HTML5 WebSockets With Pusher And ColdFusion
@Ben, Just wanted to let you know that pusher are soon to start limiting sizes on messages. This was the detail that came through in the Feb dispatch: "However, we will soon be limiting the s ... read »
Feb 3, 2012 at 5:05 PM
Regular Expressions Make CSV Parsing In ColdFusion So Much Easier (And Faster)
I tried using your RegEx in my C# program, but it was matching an extra empty-string at the end and so I would end up with an extra field that doesn't exist, so I changed it to this: (^|,)("(?: ... read »
Feb 3, 2012 at 3:47 PM
ColdFusion Supports HTTP Verbs PUT And DELETE (As Well As GET And POST)
Josh Cyr posted this on Twitter just a little bit ago. Thought it was appropriate. http://stackoverflow.com/questions/1619152/how-to-create-rest-urls-without-verbs/1619677#1619677 ... read »
Feb 3, 2012 at 2:28 PM
Changing The Execution Context Of Your Self-Executing Function Blocks In JavaScript
@Michael, You definitely make a good point (and extra points for quoting movies - I love movies). When you use a return() statement to define the object's public API, it does provide a consistent a ... read »
Feb 3, 2012 at 2:04 PM
Changing The Execution Context Of Your Self-Executing Function Blocks In JavaScript
To quote Jurassic Park: "Just because you can doesn't mean you should". I completely, utterly disagree with the thought that this is more readable. Consider the current module pattern: if ... read »
Feb 3, 2012 at 1:10 PM
REST API Design Rulebook By Mark Masse
@Jordan, Yeah, WRML was created by Mark Masse (author of the book). I also found it to be a bit convoluted. I suppose it is intended to allow the Client to be able to programmaticaly respond to cha ... read »
Feb 3, 2012 at 1:08 PM
ColdFusion Supports HTTP Verbs PUT And DELETE (As Well As GET And POST)
@Jason, To be honest, I don't have good answers for that kinds of stuff. And, to the point, that is specifically why I *really* liked the REST API Design Rulebook by Mark Masse - he just cuts throu ... read »