Throwing And Catching A File Using CFHttp For Both Actions

Posted April 2, 2007 at 1:25 PM by Ben Nadel

Tags: ColdFusion

I can't remember where I heard this, but not so long ago I heard or read about someone who wanted to send a file to another server using CFHttp. He didn't have any FTP stuff set up, so that was they best idea he had. This seemed like a fun little piece of functionality to test as I have never done that before.

I set up two pages: cfhttp_throw.cfm and cfhttp_catch.cfm. As you can probably guess, the cfhttp_throw.cfm takes a file from the local file system and "posts" it to the cfhttp_catch.cfm. The cfhttp_catch.cfm file then "uploads" it to its server and echoes back the file name as it was stored on the new machine.

This was suprisingly easy. I have not used CFHttp all that extensively and in about 10 minutes I worked out something that did just what I wanted to do. And, in the process, I used a CFHttpParam tag of type "File" which I had never done before. I have to go back and check out the rest of the CFHttpParam types to see what else I am missing (damn you ignorance!).

Here is the cfhttp_throw.cfm code. It doesn't have all the CFTry / CFCatch tags that probably should be used, but for this proof of concept, it was not necessary:

  • <!---
  • Submit the file the CFHTTP_Catch.cfm file. Notice that we
  • are sending the file via a CFHttpParam FILE tag. By using
  • this file param, CFHTTP automatically sends all form
  • fields as multi-part form data; therefore, we do NOT need
  • to specify the "multipart='true'" CFHttp attribute.
  • --->
  • <cfhttp
  • url="http://swoop/..../cfhttp_catch.cfm"
  • method="POST"
  • useragent="Mozilla/5.0 Gecko/20070309 Firefox/2.0.0.3"
  • result="objHTTP">
  •  
  • <!---
  • Send along a file via the FORM post. This acts the same
  • as a stanard form Input type="file" field and can be
  • handled as such on the "Catch" page.
  • --->
  • <cfhttpparam
  • type="FILE"
  • name="file"
  • file="#ExpandPath( './test.jpg' )#"
  • />
  •  
  • </cfhttp>
  •  
  •  
  • <cfoutput>
  •  
  • <h4>
  • CFHttp Post Result:
  • </h4>
  •  
  • <p>
  • #objHTTP.FileContent#
  • </p>
  •  
  • </cfoutput>

And, here is the cfhttp_catch.cfm code:

  • <!--- Kill extra output. --->
  • <cfsilent>
  •  
  • <!---
  • Param the form fields. Since this data is coming via
  • a CFHTTP "Post" we can operate as if it was a standard
  • form submission.
  • --->
  • <cfparam
  • name="FORM.file"
  • type="string"
  • default=""
  • />
  •  
  •  
  • <!--- Try to upload the file. --->
  • <cftry>
  •  
  • <!---
  • Upload the file. When defining the CFFile, we can
  • treat the posted file as if it was submitted via a
  • standard File Input (since it was posted as a FILE
  • using CFHttpParam).
  • --->
  • <cffile
  • action="UPLOAD"
  • filefield="file"
  • destination="#ExpandPath( './files/' )#"
  • nameconflict="MAKEUNIQUE"
  • />
  •  
  •  
  • <!---
  • Echo back the name of the file as it has been
  • saved to the server.
  • --->
  • <cfcontent
  • type="text/plain"
  • variable="#ToBinary( ToBase64( CFFILE.ServerFile ) )#"
  • />
  •  
  •  
  • <!---
  • Catch any errors that were thrown during the
  • file upload.
  • --->
  • <cfcatch>
  •  
  • <!--- Echo back the error message. --->
  • <cfcontent
  • type="text/plain"
  • variable="#ToBinary( ToBase64( CFCATCH.Message ) )#"
  • />
  •  
  • </cfcatch>
  • </cftry>
  •  
  • </cfsilent>

That was pretty cool. I like that using the proper CFHttp / CFHttpParam tags, your target page can act as if the request was coming from a standard Form-action page with standard FORM-scoped values. I think it's totally awesome that CFFile can actually upload the file that is posted to it. Very cool.




Reader Comments

Apr 2, 2007 at 1:51 PM // reply »
319 Comments

What is the deal with this?

#ToBinary( ToBase64( CFFILE.ServerFile ) )#

CFFILE.* should all be strings. So why not just output as is?


Apr 2, 2007 at 3:56 PM // reply »
11,241 Comments

@Ray,

Cause I am a sick person .... the Variable attribute of CFContent only takes binary data and won't allow string data unless you convert it to binary first (hence the ToBinary stuff). Sure, I could just output it after the CFSilent, but I don't think that looks as nice.... Like I said, I am sick (in the head) and code formatting is that special to me :)


Apr 2, 2007 at 3:57 PM // reply »
11,241 Comments

Plus, I just really like using CFContent. Feels so good.


Apr 2, 2007 at 4:29 PM // reply »
319 Comments

Hah, that is insane.


Apr 2, 2007 at 4:55 PM // reply »
11,241 Comments

What fun would "sane" be ;)


Oct 29, 2010 at 1:54 PM // reply »
16 Comments

Hey Ben,

I've been playing around with drag-n-drop uploads using jQuery and XMLHttpRequest Level 2. Check out: http://onehub.com/blog/posts/designing-an-html5-drag-drop-file-uploader-using-sinatra-and-jquery-part-1

Basically it's a PUT method and not sure if this relates with exactly what you are doing here, but it seems to be somewhat the same.

I can get the PUT to work great, but I'm having problems with the "catcher" file, since obviously this is not using traditional form fields. Have you had any experience playing around with this yet?


Oct 29, 2010 at 2:53 PM // reply »
16 Comments

@Ben

I think I answered my own question.

Looks like you can grab the XHR data using ColdFusions "GetHttpRequestData()" function. So to capture the file and save you would do something like this:

<cfset xhr_data = GetHttpRequestData() />
<cffile action="write" file="#ExpandPath('.')#/#CGI.HTTP_X_FILENAME#" output="#xhr_data.content#">

p.s. this doesn't work so well on older browsers.


Nov 1, 2010 at 9:07 PM // reply »
11,241 Comments

@Doug,

I've played around very briefly with the XMLHttpRequest 2 API; from the little that I've read up on it, you should be able to actually create a multi-part form request that acts juts like a native request. I think this is the blog post that I learned from:

http://blog.igstan.ro/2009/01/pure-javascript-file-upload.html

Of course, this only works in like FireFox 3.6 which is like the most current few releases.


Nov 1, 2010 at 11:12 PM // reply »
16 Comments

@Ben,

Cool, I'll check it out.

The one I linked to above works in everything except IE. I've gotten it to work with the "PUT" method, but I'm struggling a little bit with the normal "POST" fallback option.

I'm sure I'll figure it out. Thanks.


Nov 3, 2010 at 10:32 PM // reply »
11,241 Comments

@Doug,

If you have your stuff working in everything but IE, disregard my link. I believe the example in the link I sent you *only* works in the latest Firefox releases. Sounds like you are on a better track than me.


Feb 4, 2011 at 10:35 AM // reply »
2 Comments

This is a good post! This is about sending a file with a http post request from Server A to Server B. I have a question about doing something slightly different.

what if server A wants to download a file from server B via an http request. so in essennce an http download. Is it something to do with what you set in cffilecontent response type? How nice it would be if there was a working example somewhere.

Thanks!


Feb 4, 2011 at 1:00 PM // reply »
2 Comments

I guess i figured it out. I would need this on the httpResponse

<cfheader name="Content-Disposition" value="inline; filename=testing.doc">
<cfcontent type="application/msword" file="#fileName#" deletefile="no">

and something like this on the requester file.

<cfscript>
ioOutput = CreateObject("java","java.io.FileOutputStream");
ioOutput.init("C:\...\testing.doc");
objHTTP.Filecontent.writeTo(ioOutput);
ioOutput.close();
</cfscript>


Jun 15, 2011 at 10:41 AM // reply »
1 Comments

Nice post!



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
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 22, 2013 at 12:44 PM
Ask Ben: Query Loop Inside CFScript Tags
In cf10, if you call a function that has: local.result = {}; local.result.msg = ""; local.svc = new query(); local.svc.setSQL("SELECT * FROM..."); local.obj = local.svc.exe ... read »
May 22, 2013 at 12:29 PM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben: What version of Java are you using? Also, did you test users.id to see what Java reports as the data type? I wonder if it's not a Java primitive data type, but getting returned as something ... read »
May 22, 2013 at 11:47 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Dana, Awesome - so it looks like this bug was fixed in ColdFusion 10. Thanks so much for double-checking that. ... read »
May 22, 2013 at 11:37 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
When I c&p and run on cf10, I get: Selected User IDs: 1,4 User 1 selected: YES - YES User 2 selected: NO - NO User 3 selected: NO - NO User 4 selected: YES - YES User 5 selected: NO - ... read »
May 22, 2013 at 11:27 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Tom, Good thought, but no dice. Both of these still exhibit the same behavior: users.id[ users.currentRow ] users[ "id" ][ users.currentRow ] It's just something whacky happening with ... read »
May 22, 2013 at 11:07 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
Could your problem be that "users.id" is actually an ARRAY, not a single value? Perhaps try it again with "users.id[1]" (I only have CF8 here at work). ... read »
May 22, 2013 at 7:52 AM
Nested Views, Routing, And Deep Linking With AngularJS
Hi, Just a quick thank you. As it happens, for my own purposes, the pending ui-router work being done in native angular is likely the one I'll adopt, but your exploration, code and documentation of ... read »
May 22, 2013 at 4:43 AM
How Do You Use The ColdFusion CFParam Tag?
'<cfparam>' or 'isDefined()and <cfset>' performs the same task.Is there any difference? ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools