Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at Scotch On The Rocks (SOTR) 2011 (Edinburgh) with: Chris Laslett

Converting A Base64 Value Back Into A String Using ColdFusion

Posted 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

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.

Reply to this Comment

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!

Reply to this Comment

@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 :)

Reply to this Comment

@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

Reply to this Comment

@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

Reply to this Comment

@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?

Reply to this Comment

@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

Reply to this Comment

@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>

Reply to this Comment

How can I check if a string is in Base64 format?

I have a Base64 value (sometimes) like, "IiZQWCAK" and I want to check that to see if it's in base64 format before trying to decode it with Decrypt(ToString(ToBinary(variables.Base64String)), Application.encryptKey). How can I go about accomplishing that?

Any help would be great. Thanks!

Reply to this Comment

I forgot to post the error I get in regards to the above question. If I entered in the value -1 for example, it would throw an error. The error it throws is:

The parameter 1 of function ToBinary, which is now -1 must be a base-64 encoded string.

I need to protect against that somehow.

Reply to this Comment

I know this is an older post, but we have a project where we have to insert images into the DB. The database datatype is Varchar(max) and the images have to be base64 encoded.

This works fine except for transparent PNG's. the alpha channel keeps getting dropped.

We can make it work with a blob, but the developers of the iOS app says that they have to be base64.

So my question is, is it possible with CF to import and image turn it into a blob then encode it to base64 and retain the alpha channel?

Reply to this Comment

Post A Comment

?
You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
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.