user1594257
user1594257

Reputation: 495

ColdFusion combine base64 chunks from web service into binary file

I'm consuming a web service that returns large files in base64 chunks. When the web service only returns 1 chunk I can use toBinary() to convert and save to a file. But I'm not sure what to do when I get back larger files that are broken into chunks of base64 strings. A simple variable concatenation does not work. Is there a proper way to join these strings in Cold Fusion and then convert toBinary?

<cfset masterChunk = masterChunk & theNextChunk />
<cfset binaryFile = toBinary(masterChunk) />

The error I get is: must be a base-64 encoded string.

Upvotes: 3

Views: 688

Answers (2)

Leigh
Leigh

Reputation: 28873

(Just to throw out a few more ideas ...)

Concatenating multiple base64 strings worked fine for me, so there may be something more going on here. Hard to say without the actual strings.

That said, if the ultimate goal is saving the binary to a file, why not just append the decoded bytes directly to the file? It is simpler and can be used with physical files as well as those in ram:///:

    // open for appending
    output = FileOpen( "c:/path/to/file.ext, "append");

    // append decoded bytes
    FileWrite(output, binaryDecode(firstChunk, "base64"));
    FileWrite(output, binaryDecode(nextChunk, "base64"));
    // ... append more bytes

    FileClose(output);

If you really need an array, another possibility is using a ByteArrayOutputStream. Again, it is slightly simpler to use, and is suitable for moderate sized files. For larger files, a ByteBuffer is probably more memory efficient.

    baos = createObject("java", "java.io.ByteArrayOutputStream").init();

    // append decoded bytes
    baos.write( binaryDecode(firstChunk, "base64") );
    baos.write( binaryDecode(nextChunk, "base64") );
    baos.close();

    // do something with the array (save to file, etcetera)
    FileWrite( "c:/path/to/file.ext", baos.toByteArray());

Edit: Side note, ToBinary is deprecated. The docs recommend using BinaryDecode for new code.

Upvotes: 1

user1594257
user1594257

Reputation: 495

I was able to adapt what I found in this post: http://www.bennadel.com/blog/1017-splitting-and-joining-a-binary-file-in-coldfusion.htm

<!--- create array to hold binaries --->
<cfset xmlBinaries = arrayNew(1)/>
<cfset xmlBinariesTotalLen = arrayNew(1)/>
<!--- append chunks --->
<cfset arrayAppend(xmlBinaries,toBinary(newBase64Chunk))/>
<!--- set up java buffer to hold binary chunks --->
                <cfset objByteBuffer = CreateObject(
                    "java",
                    "java.nio.ByteBuffer"
                    ) />

<cfloop from="1" to="#arraylen(xmlBinaries)#" index="i">
 <cfset arrayAppend(xmlBinariesTotalLen,ArrayLen(xmlBinaries[i])) />
</cfloop>

<!---allocate space in the buffer --->
<cfset arrBinFull = objByteBuffer.Allocate(
                    JavaCast(
                    "int",
                    (ArraySum(xmlBinariesTotalLen) )
                    )
                    ) />

<!---add binaries to the buffer --->
<cfloop from="1" to="#arraylen(xmlBinaries)#" index="i">
<cfset arrBinFull.Put(
                        xmlBinaries[i],
                        JavaCast( "int", 0 ),
                        JavaCast( "int", ArrayLen( xmlBinaries[i] ) )
                        ) /> 
</cfloop>


<cfset myResponse.fullBinary = arrBinFull.Array() />

Upvotes: 0

Related Questions