3

We are trying to interact with a RESTful web service that expects a file.

I set the name of the field to data (as required by the API) and then specify the file as an absolute path. When the file makes it to the server, the filename in the HTTP transaction is the complete absolute path.

This causes a problem with the API as the full path is then recorded as the "FileName".

How do I get ColdFusion to report only the file name rather than the full path?

We are using ColdFusion 9.

Here is the CFML:

<cfhttp url="http://server/testcode"
        port="9876"
        method="post"
        result="Content">

    <cfhttpparam    type="file"
                    name="data"
                    file="c:\temp\testfile.txt">
</cfhttp>

Here are some examples of the HTTP interactions with different browsers:

CFHTTP 9
-------------------------------7d0d117230764
Content-Disposition: form-data; name="data"; filename="c:\temp\testfile.txt"
Content-Type: text/plain

This is the text, really long, well, not really.

-------------------------------7d0d117230764--



IE8
-----------------------------7db370d80e0a
Content-Disposition: form-data; name="FileField"; filename="C:\temp\testfile.txt"
Content-Type: text/plain

This is the text, really long, well, not really.
-----------------------------7db370d80e0a--


Chrome 13
------WebKitFormBoundaryDnpFVJwCsZkzTGDc
Content-Disposition: form-data; name="FileField"; filename="testfile.txt"
Content-Type: text/plain

This is the text, really long, well, not really.

Firefox 6
-----------------------------22798303036224
Content-Disposition: form-data; name="FileField"; filename="testfile.txt"
Content-Type: text/plain

This is the text, really long, well, not really.
-----------------------------22798303036224--

Apparently IE8 and CFHTTP both do the same thing (add "c:\temp" to the file name). I'm not sure what the spec for HTTP is, but it would be nice if there was a way to get CFHTTP to leave the path off.

Is there any way to do this?

Tom Hubbard
  • 15,820
  • 14
  • 59
  • 86

4 Answers4

4

I ran into a problem similar to yours, once. I didn't care about excluding the path, but I wanted to send a different filename than the name of the file on my server's filesystem. I could not find a way to do it using CF tags at all, but I was able to get it to work by dropping into Java. I used org.apache.commons.httpclient, which ships with CF9 IIRC. It goes something like this (pardon any typos, I'm transposing from more complicated code):

oach = 'org.apache.commons.httpclient';
oachmm = '#oach#.methods.multipart';
method = createObject('java', '#oach#.methods.PostMethod').init(post_uri);
filePart = createObject('java', '#oachmm#.FilePart').init(
  'fieldname',
  'filename',
  createObject('java', 'java.io.File').init('filepath')
);
method.setRequestEntity(
  createObject('java', '#oachmm#.MultipartRequestEntity').init(
    [ filePart ],
    method.getParams()
  )
);
status = createObject('java', '#oach#.HttpClient').init().executeMethod(method);
method.releaseConnection();
Josh
  • 992
  • 5
  • 5
  • Thanks, I'm starting to realize that this is the way to go. Turns out, at least in regard to CFML, SOAP is a lot easier than REST. – Tom Hubbard Sep 15 '11 at 10:51
  • I had this problem today on a CF10 server. Or possibly it was the "extra blank line" problem described at [an even older question](http://stackoverflow.com/q/3738580/2404501) - either way, cfhttp was unusable because of its bugginess. The solution given above with HttpClient worked. –  Jul 16 '15 at 19:11
3

I see that the content type is text/plain so first I think that you need to add the multipart property on the CFHTTP

<cfhttp url="http://server/testcode"
        port="9876"
        method="post"
        result="Content"
        multipart = "yes">

    <cfhttpparam    type="file"
                    name="data"
                    file="c:\temp\testfile.txt">
</cfhttp>

Could solve your issue.

Cyril Hanquez
  • 686
  • 3
  • 6
  • Thanks, the content-type that you are seeing there is for the file, which is a .txt. CFHTTP automatically throws it into multipart mode with the existence of the file parameter. This can be seen in the header information which I did not include in the post. – Tom Hubbard Sep 13 '11 at 15:07
  • You're right... now can you clarify something: how important is the filename regarding the usage of the API? I mean, you're transferring the file as binary data, is the name of the file used anywhere by the API? Is it possible to have more information on the API itself? – Cyril Hanquez Sep 14 '11 at 08:39
  • It's the WatchDox api, which is a file security system. It builds a file list which keeps the original file name (with the slashes removed) so when you go to save the file the suggested filename is "c:temptestfile.txt". – Tom Hubbard Sep 15 '11 at 10:50
2

The only difference I see between all of the posts is that CF is sending name="data" while everything else is sending name="FileField". If the other browser submissions are correct, then I would change your cfhttpparam:

<cfhttpparam    type="file"
                name="FileField"
                file="c:\temp\testfile.txt">

or even try sending an additional FileName parameter:

<cfhttpparam    type="file"
                name="data"
                file="c:\temp\testfile.txt" />

<cfhttpparam    type="formField"
                name="FileName"
                value="testfile.txt" />
Dan Short
  • 9,598
  • 2
  • 28
  • 53
  • Thanks Dan, this is how I would prefer it to be handled as well, In fact ColdFusion itself (non CFHTTP) kind of does it this way. Unfortunately, I have no control over the API which requires the field to be called data. It does not expect an independent filename field so would ignore one. – Tom Hubbard Sep 15 '11 at 10:46
0

So I was able to get access to the API and made it work. Here is the code for this specific part (as I assume that you were able to login and get a document guid).

<!--- upload a document --->
<cfhttp method="post" url="<path to watchdox api upload>/#local.guid#/upload">

    <cfhttpparam type="header" name="Content-type" value="multipart/form-data">
    <cfhttpparam type="header" name="x-wdox-version" value="1.0">
    <cfhttpparam type="header" name="x-wdox-ssid" value="#local.xwdoxssid#" >
    <cfhttpparam type="formfield" name="filename" value="testfile.txt" >
    <cfhttpparam type="file" file="c:\temp\testfile.txt" name="data" >

</cfhttp>

Hope it will help.

Cyril Hanquez
  • 686
  • 3
  • 6
  • By the way, Dan was right with is proposal :-) But without knowing the API, it's not easy to answer... – Cyril Hanquez Sep 16 '11 at 14:21
  • Thanks. I have tried that. Does not work for us. We end up with a file name that says: c:temptestfile.txt. If I add in the documentName parameter into the post it will change the display name, but the underlying file name (when you go to view/save) still has the path stuff in it. – Tom Hubbard Sep 19 '11 at 11:15