posted: 30 Jun 2011
I mentioned in this post that I had been having issues with cfhttp and uploading files. Well, the solution that I proposed in that post used a String object, into which the file contents were read, before assembling the response. This works well, but it does impose the overhead that the file is read into memory before being passed to the destination. This obviously starts to cause problems when we get large files being uploaded and so I started looking for another alternative.
I'm not sure what underpins the implementation of cfhttp in ColdFusion (I presumed in was Apache commons httpclient) but I thought I'd give that a go regardless, since it's already available to CF as it comes already inside the cfusion/libs directory. The 3.1 version has now been superseded, but I managed to locate the Javadocs and some example code, so thought I'd give it a try.
Here's what I came up with:
<cfset objFile = CreateObject("java", "java.io.File")>
<cfset uploadUrl = request.rhino.getLocal("docapiurl", true)>
<cfset commonsHttp = CreateObject("java", "org.apache.commons.httpclient.HttpClient")>
<cfset commonsHttpPost = CreateObject("java", "org.apache.commons.httpclient.methods.PostMethod")>
<cfset commonsHttpFilePart = CreateObject("java", "org.apache.commons.httpclient.methods.multipart.FilePart")>
<cfset fileName = GetFileFromPath(filepathandname)>
<cfset commonsHttpFilePart.init("file", filename, objFile)>
<cfset commonsHttpMeta = CreateObject("java", "org.apache.commons.httpclient.methods.multipart.StringPart")>
<cfset commonsHttpMeta.init("meta", xmlString)>
<cfset commonsHttpAction = CreateObject("java", "org.apache.commons.httpclient.methods.multipart.StringPart")>
<cfset commonsHttpAction.init("action", "upload")>
<cfset httpParts = [commonsHttpFilePart, commonsHttpMeta, commonsHttpAction]>
<cfset commonsHttpMultipartRequest = CreateObject("java", "org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity")>
<cfset commonsHttpMultipartRequest.init(httpParts, commonsHttpPost.getParams())>
<cfset status = commonsHttp.executeMethod(commonsHttpPost)>
<cfset uploadResponse = commonsHttpPost.getResponseBodyAsString()>
It seems to be working well, so in case you run in to cfhttp problems, give some Java a try.
Samples: http://svn.apache.org/viewvc/httpcomponents/oac.hc3x/trunk/src/examples/ (MultipartFileUploadApp.java