Ask Ben: Posting XML And File Data With ColdFusion And CFHttp

Posted December 4, 2008 at 12:25 PM by Ben Nadel

Tags: ColdFusion, Ask Ben

I am using CFHTTP to send a multipart message XML and an image file (fax tiff), the question I have is how do you send a XML type and File type in the same post? I have tried using cfhttp type designator, but cold fusion errors saying that you can not have both a XML and File type.

The problem here is that you are using the ColdFusion CFHttpParam type of "XML". If you use CFHttpParam type of "XML" or "Body", you cannot mix in other pieces of data because XML and Body are designed to be the only data going across (the entire body of the message). In fact, if you designate the type, XML, behind the scenes, it is actually using type, Body, and setting the mime type to be "text/xml". As such, the XML type is merely a short-hand for the type Body.

If you try to mix and match, you will get the following ColdFusion error (as you have probably seen):

You cannot mix the use of cfhttpparam tags of type file or formfield with cfhttpparam tags of type body or XML.

This is not a problem, however; all we need to do is not use type XML or Body when posting multiple pieces of information. If we need to POST some XML and a file, let's just treat this like it's a standard form post and post each of these datum as if they were form data:

  • <!--- Define our generic CFHTTP properties. --->
  • <cfset objCFHttpProperties = {
  • Useragent = "#CGI.http_user_agent#",
  • Username = "xxxxxxx",
  • Password = "yyyyyyy"
  • } />
  •  
  •  
  • <!---
  • Get the URL for our post. Since CFHttp requires a full
  • URL, not just a relative one, we need to build it.
  • --->
  • <cfset strURL = (
  • CGI.server_name &
  • GetDirectoryFromPath( CGI.script_name ) &
  • "cfhttp_catch.cfm"
  • ) />
  •  
  •  
  • <!--- Create the XML data to post. --->
  • <cfxml variable="xmlPurchaseData">
  •  
  • <transaction>
  • <type>Debit</type>
  • <cost>19.95</cost>
  • <date>12-04-2008</date>
  • <item>
  • <sku>BTC-CANADA-07189</sku>
  • <name>Better Than Chocolate</name>
  • </item>
  • </transaction>
  •  
  • </cfxml>
  •  
  •  
  • <!--- Create the file path to the DVD cover. --->
  • <cfset strFilePath = ExpandPath( "./cover.jpg" ) />
  •  
  •  
  • <!---
  • Now, we are going to post the XML data along with the
  • cover of the movie that we are pretending to purchase.
  • --->
  • <cfhttp
  • url="#strURL#"
  • method="POST"
  • result="objGet"
  • attributecollection="#objCFHttpProperties#">
  •  
  • <!---
  • When posting the XML data, ColdFusion will worry
  • about converting the XML document back into a string.
  • --->
  • <cfhttpparam
  • type="formfield"
  • name="purchase_data"
  • value="#xmlPurchaseData#"
  • />
  •  
  • <!--- Post the file. --->
  • <cfhttpparam
  • type="file"
  • name="cover"
  • file="#strFilePath#"
  • mimetype="image/jpeg"
  • />
  •  
  • </cfhttp>
  •  
  •  
  • <!--- Output the return message. --->
  • Message: #objGet.FileContent#

As you can see here, we are performing a FORM POST. The Xml data is being send over as a form field and the file is being sent across as a file (specialized form field). Nothing special going on.

This data is being posted to the following "catch" page:

  • <!--- Param the form fields. --->
  • <cfparam name="FORM.purchase_data" type="string" default="" />
  • <cfparam name="FORM.cover" type="string" default="" />
  •  
  •  
  • <!--- Write the purchase data to file. --->
  • <cffile
  • action="write"
  • file="#ExpandPath( './purchase_data.xml' )#"
  • output="#FORM.purchase_data#"
  • />
  •  
  • <!--- Upload the DVD cover. --->
  • <cffile
  • action="upload"
  • filefield="cover"
  • destination="#ExpandPath( './' )#"
  • nameconflict="makeunique"
  • />
  •  
  •  
  • <!--- Return response string. --->
  • <cfcontent
  • type="text/plain"
  • variable="#ToBinary( ToBase64( 'Processing Done!' ))#"
  • />

This "catch" page looks and acts just like any standard ColdFusion form processing page. We are treating the posted data as if they were FORM-scoped data because, in fact, that is what they are. Once we accept this, we can then process the form data as we would normally (here I am saving the XML and image to file).

I hope this helps.




Reader Comments

Dec 4, 2008 at 12:45 PM // reply »
319 Comments

The problem I have with your solution is that sometimes the receiver of the data requires you to post the data as a multipart http post. Splitting it up into two form fields only works if you have control over the receiver.

As an example, when I had to do my file uploads for youtube (http://youtubecfc.riaforge.org), I had to do both an XML field and a file field. This is the code I used:

<cfhttp url="#theurl#" method="post" result="result" multiparttype="related">
<cfhttpparam type="header" name="Authorization" value="GoogleLogin auth=#variables.authtoken#">
<cfhttpparam type="header" name="X-GData-Client" value="youtubecfc">
<cfhttpparam type="header" name="X-GData-Key" value="key=#variables.devkey#">
<cfhttpparam type="header" name="Slug" value="#listLast(arguments.video,"\/")#">
<cfhttpparam type="file" name="API_XML_Request" file="#tmpfile#" mimetype="application/atom+xml; charset=UTF-8 ">
<cfhttpparam type="file" name="file" file="#arguments.video#" mimetype="video/*">
</cfhttp>

Notice the XML is sent as a file (only sucky part, I had to save the XML string to the file system) and includes a mimetype.

Note - this code makes use of the new multipart=related argument that was added per a hotfix for cf7 and 8. Ie, this is not part of the documented CF language, although it is "official" if you get the hotfix.


Dec 4, 2008 at 12:51 PM // reply »
11,246 Comments

@Ray,

Interesting. I guess I have never had to do a real "multi-part" post. I just thought the Asker meant that he was trying to submit several parts of data. I am assuming he was trying to post XML and File types (which is why he was getting an errror).

This is good to know though - I have never come up against this, so I am sure it will save me headache when I do. Thanks!


Dec 4, 2008 at 1:01 PM // reply »
319 Comments

Don't get me started on Google and their freaking APIs. (Since Google owns YouTube now they had to make the api 'better')


Dec 4, 2008 at 1:04 PM // reply »
11,246 Comments

@Ray,

Ha ha, breathe breathe :)


Sep 14, 2010 at 10:36 AM // reply »
7 Comments

sigh, no luck on railo, multiparttype="related" not supported :((
Anyway I got videos uploaded with CF9 in a few minuts, thanks a lot !!


Sep 14, 2010 at 9:38 PM // reply »
11,246 Comments

@Philippe,

Glad you got it working. I've yet to experiment with the multipartType yet. Thanks for the reminder that this was out there.


Aug 27, 2012 at 2:01 AM // reply »
1 Comments

@ben
thanks
the content was really helpful...


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 24, 2013 at 5:39 PM
Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion
@Adam Oops! My mistake! I hadn't gotten that far in my testing - I'm still baby stepping my way through the process. ... read »
May 24, 2013 at 5:13 PM
Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion
Hi Jason, Thanks for checking up on that, but I still stand firm on my position. :) There are actually two listLast()'s in use, and you're right that the one using a space as a delimiter is fine. ... read »
May 24, 2013 at 4:45 PM
Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion
@Ben I have been lurking your site for quite some time, and haven't stepped up to comment until today. Thanks for all the great info - keep it up! @Adam I believe you are mistaken... as the commen ... read »
May 24, 2013 at 11:21 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@WebManWalking, Ha ha, let's us never speak of justifying "##" notation again :P ... read »
May 24, 2013 at 11:18 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben, Ah, so it was indeed how I vaguely remembered it to be: A direct assignment value = users.id[ i ] causes value to retain the sticky datatype of the query column. Although unnecessary in ... read »
May 24, 2013 at 9:11 AM
Preventing Links In Standalone iPhone Applications From Opening In Mobile Safari
@Brandon, Hi, No, I haven't been able to do that. I have just kept it as it is. ... read »
May 23, 2013 at 9:52 PM
Preventing Links In Standalone iPhone Applications From Opening In Mobile Safari
@Muhmmadibn Did you figure out a solution to launching PDFs? I am running into the same issues myself. There is no way to close the PDF or go back once you launch it. Thanks in advance! ... read »
May 23, 2013 at 6:06 PM
The Girl Who Broke My Heart, And Made Me A Better Person
Good day,ladies and gentle men, my name is Dr AMADI the great spell caster in Africa, i have help so many people for different kind of problems,who say there is no solution to problems on earth, that ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools