I had an interesting issue come up this morning that strikes me as worthy of sharing. I don't know about anyone else but I've always been puzzled by the curious yellow boxes that one sees occasionally in a CFDUMP of certain data structures. These yellow boxes represent Java byte[] (or byte array) objects. I've never really "gotten" them until I realized something.
A byte[] is just what the name implies... an array of 8-bit memory locations. ASCII characters are single-byte characters, so you can use a byte[] to hold a stream of single ASCII characters when you're doing things like reading or writing files in a Java application. Or you can encode them full of binary data. It doesn't really matter except that each cell in the array can only hold one byte.
Which got me thinking... the data I needed access to was in the array, and my other attempts at using toString(binaryData) just weren't robust enough. So in a fit of random curiosity I decided to use an index loop on it and see what I got... and I got a list of numbers. Each array element held an integer. I have no idea why I tried what I tried next, but I was blown away. It worked.
As I looped over the array, I called chr(array[i]) and it made words!
Actually this was an attempt to use the getHTTPRequestData() to get Content-Disposition HTTP headers, and with a bit of CFIF magic it worked out really well. I ended up writing a UDF that works as a wrapper to be used intsead of cffile action="updload". The code is posted below.
Also, here's a running demo. <cffunction name="getFileUploadData" returntype="struct" access="public" output="false">
<cfargument name="httpRequest" type="struct" required="true" />
<cfargument name="formScope" type="struct" required="true" />
<cfset var retVal = structNew()>
<cfset var content = httpRequest.content>
<cfset var headers = "">
<cfset var headerArray = "">
<cfset var i = 0>
<cfset var tmp = "">
<cfset retVal.uploadTmpFile = arguments.formScope.file>
<cfsavecontent variable="headers">
<cfoutput>
<cfloop from="1" to="#arrayLen(content)#" index="i"><cfset tmp = content[i]><cfif tmp LT 1><cfbreak /><cfelseif find(tmp,"10,13")>|<cfelse>#chr(tmp)#</cfif></cfloop>
</cfoutput></cfsavecontent>
<cfset headerArray = listToArray(headers,"||")>
<cfloop from="1" to="#arrayLen(headerArray)#" index="i">
<cfif findNoCase("Content-Type",headerArray[i])>
<cfset retVal.contentType = trim(listLast(headerArray[i],":"))>
<cfelseif findNoCase("Content-Disposition",headerArray[i])>
<cfset retVal.originalFileName = trim(listLast(listLast(headerArray[i],";"),"="))>
<cfset retVal.originalFileName = mid(retVal.originalFileName,2,len(retVal.originalFileName)-2)>
</cfif>
</cfloop>
<cffile action="readbinary" file="#retVal.uploadTmpFile#" variable="retVal.fileData" />
<cfreturn retVal>
</cffunction>
Comments
As promised: tideli-tideli-tiiIIIIII
Posted By Trond Ulseth / Posted At 10/4/05 4:25 PM
this reminds me of the (then kludgy but necessary) way of doing file uploads in ASP (classic) circa 1999 where the file was streamed to a record set object as binary data and assembled there.
don't laugh. it worked. it was the only thing we had...
Posted By barry.b / Posted At 10/4/05 5:18 PM
Hey barry... whatever works, man!
In the face of missing functionality a working solution is superior to an unfilled need, right?
Laterz!
Posted By Jared Rypka-Hauer / Posted At 10/4/05 5:19 PM
Hey Jared,
Looks cool. What's the advantage to this over using cffile action="upload" ? I'm curious.
Posted By Nando / Posted At 11/10/05 2:06 AM
Hello everybody,
Nando, I know this comes a bit late, but the advantage would be in a cfc because this method would not break encapsulation.
I found a couple problems with this method. One, it only works if you have one file in your upload. Two, if you made it work for multiple files it would become very slow as it would have to loop through the file content in the header.
Jared, I have a method I based off this that does multiple files and runs fairly quick. I don't know if you would be interested in taking a look, but I wouldn't doubt my own could use room for improvement.
Posted By Daniel Budde II (VVraith) / Posted At 1/10/07 10:30 AM
Hi Daniel,
I was looking for some CF code to upload multiple files (upto a 1000 files) at a time. Is there a way you could post your code?
Also, is there a limit on the number (or total size) of files that could be posted (http post) at one time?
Thanks!
Posted By Preethi / Posted At 2/5/07 1:27 PM
Hello Jared,
This method no longer works in CF8. GetHTTPRequestData().content no longer returns the byte array from the post. It now returns an empty byte array. See this post on the forums.
http://www.adobe.com/cfusion/webforums/forum/messageview.cfm?forumid=72&catid=648&threadid=1280872&enterthread=y
Posted By Daniel Budde II / Posted At 6/30/07 4:09 PM
Nice site.
Look here:
<a href= http://xanaxtramadol.com/www.89.com/map.html >www.89.com</a> [url=http://xanaxtramadol.com/www.89.com/map.html]www.89.com[/url] <a href= http://xanaxtramadol.com/online-marketing/map.html >online marketing</a> [url=http://xanaxtramadol.com/online-marketing/map.html]online marketing[/url] <a href= http://xanaxtramadol.com/car-donation/map.html >car donation</a> [url=http://xanaxtramadol.com/car-donation/map.html]car donation[/url] <a href= http://buyasoma.com/criminal-attorney-los-angeles/map.html >criminal attorney los angeles</a> [url=http://buyasoma.com/criminal-attorney-los-angeles/map.html]criminal attorney los angeles[/url] <a href= http://buyasoma.com/cheap-domain-names/map.html >cheap domain names</a> [url=http://buyasoma.com/cheap-domain-names/map.html]cheap domain names[/url] <a href= http://buyasoma.com/directv/map.html >directv</a> [url=http://buyasoma.com/directv/map.html]directv[/url] <a href= http://buyasoma.com/fioricet-180/map.html >fioricet 180</a> [url=http://buyasoma.com/fioricet-180/map.html]fioricet 180[/url]
Posted By npp_oumze / Posted At 10/4/09 5:06 AM