4

I'm not sure I understand how to phrase my question, but I believe it's specific to ColdFusion's handling of certain AJAX form data, despite my reference to a specific JavaScript plugin.

I'm trying to implement the FilePond uploader on a ColdFusion 2011 server, and I've got it configured well on the frontend (it uploads the files to tmp folder just fine), but my problem is not knowing how to get ColdFusion to process the extra metadata it sends along with it on every upload. This data doesn't look to me like it comes in the same format as plain old hidden input fields.

When I inspect the network request with Dev Tools, it looks different to me than other forms I've processed. There are two "filepond" entries, one a JSON object and the other the binary image. When I < cfdump var="#form.FilePond#">, I only get the tmp uploaded file path, which I can process. But how do I access the JSON in my screenshot containing the "parentid"? Nothing I've tried, like form.FilePond[1], seems to work and throws errors.

I want to get ColdFusion to process the "parentid" value

Update with output from CF form processing page:

1st line is output of Form.FilePond.

2nd is cfdump of Form.

3rd is cfdump URL.

4th is cfdump of getHttpRequestData()

SOS
  • 6,430
  • 2
  • 11
  • 29
Michael
  • 2,546
  • 2
  • 20
  • 26
  • The JSON is still serialized as string in `FORM.filepond`, so you would need to `response = deserializeJSON(FORM.filepond)` to get the JSON as CF struct. You can then access it like `response.parentid`. – Alex Mar 12 '19 at 22:50
  • On closer inspection: The screenshot shows the POST payload that was sent via request. Aren't you interested in the response after the request was sent? Check the `Response` tab. – Alex Mar 12 '19 at 22:57
  • I'm showing you the headers so you can see the values this JavaScript uploader creates and sends to my server that I'm trying to process with ColdFusion. – Michael Mar 12 '19 at 23:02
  • When I #Form.filepond#, it gives me the temp file: c:\my-server-path-here\cfusion\runtime\work\Catalina\localhost\tmp\neotmp2603339573150602984.tmp – Michael Mar 12 '19 at 23:03
  • ...so obviously if it's only giving me that, if I try to deserializeJSON(Form.filepond), I get "JSON parsing failure at character 1:" – Michael Mar 12 '19 at 23:06
  • Try dumping the whole scope: FORM and URL - also `getHttpRequestData()`. – SOS Mar 12 '19 at 23:16
  • Yeah, tried those. I've updated the question and added a screenshot of my results, and nothing contains the JSON object I see being passed on my network request inspection that I highlighted in the first screenshot. In fact, the cfdump of my FORM contains two fieldnames, yet the value only contains the temp image. I would have expected to see something here. – Michael Mar 12 '19 at 23:34
  • What is the "fuseaction"? Is something else intercepting the request? – SOS Mar 12 '19 at 23:42
  • Interesting. Just noticed `form.fieldnames` shows "filepond" twice. Maybe CF is ignoring the second value? What happens if you add `this.sameformfieldsasarray = true` to your Application.cfc and dump the scopes again? – SOS Mar 12 '19 at 23:48
  • That’s just a controller pointing to this file that contains the cfdumps. I don’t think anything is intercepting. The entire scope should be there. It’s not forwarding or anything like that - just some cfincludes - but I will start deconstructing this tomorrow into a stripped down example. Something else just feels different to me about how this JS uploader passes along its data from what I’m used to dealing with via simple file uploads and form processing. I’ve done a simple input type=file upload tons of times. – Michael Mar 12 '19 at 23:50
  • Thanks for the Application.cfc recommendation. I’ll try it tomorrow when the computer is back on! – Michael Mar 12 '19 at 23:52
  • 1
    Edit: Just tried the application.cfc setting and no change. I did find [this blog](http://www.stillnetstudios.com/get-filename-before-calling-cffile/) . It uses an undocumented feature form.getPartsArray() does allow you extract the two fields. (I tested [this code](https://pastebin.com/S6P2Mux5) using a cfhttp post containing a "file" and "formfield" with the same name.) Not ideal, but at least it should confirm the data is being posted - CF just isn't showing it in the FORM scope. – SOS Mar 13 '19 at 00:31
  • It's OT, but I'll throw out my PSA that CF11 is EOL in about a month and a half, so no more security updates. https://www.carehart.org/blog/client/index.cfm/2018/12/20/CF11_countdown_clock_is_ticking – Shawn Mar 13 '19 at 00:46
  • Ageax - YES!! Thank you!! form.getPartsArray() gets everything I need. Can't believe I haven't come across this particular scenario before. I'm still not sure the difference between what causes this scenario vs submitting two < input >s with the same name (because doesn't CF usually just treat the latter as a list or array using the same field name?), but at least I've found my answer. If you want to post an answer I'll mark it as the solution. Thanks so much!! I spent toooo much time on this yesterday before coming to Stack Overflow. – Michael Mar 13 '19 at 14:40
  • Shawn - OT, but thank you, because I actually wasn't aware! Yikes. :\ CF isn't our primary app server anymore, but we've got a ton of old code on it, so we'll throw it in our queue to upgrade. Our license is tied to our AWS EC2, so I think we're gonna have to spin up a new EC2 VS simply upgrading the existing, which seems like a pain. I wish Adobe supported for more than 5 years. – Michael Mar 13 '19 at 14:47
  • 2
    @Michael - Glad it helped. Just remember it's undocumented, so be sure to isolate the code for easier alterations in case adobe changes or removes that feature in the future ;-) As far as "why", I suspect it's due to the fact that one of the fields contains a "file" and the other doesn't. Haven't really thought about what the "correct" behavior should be in this case (converting to a csv list seems weird). But I don't think CF should just drop one of the field values on the floor, as it seems to be doing. That seems like a bug. (I'll write up an answer later) – SOS Mar 13 '19 at 16:21
  • @Michael Yeah, EOL issues can suck, but they do serve a big purpose, and 5 years of security patches isn't that bad. Amazon should have worked with you to get upgraded when they stopped selling CF11 to new customers, but that's a different issue. At least there was a CF11 patch at the beginning of this month. But in all honesty, when I've looked at software I wrote just 5 years ago, I realize how many things have improved in that time (especially security). Glad Ageax got you squared away. But do heed the caution about undocumented functionality. :-/ – Shawn Mar 13 '19 at 21:04
  • Yeah, Adobe can and has changed internal functions before, so fair warning ;-) Normally I wouldn't suggest the undocumented route, but since it appears to be a bug, it's limits your choices. Granted, you could always modify the js lib as well. – SOS Mar 13 '19 at 23:24

1 Answers1

1

Update:

Bugs filed for CF2016 (core support ending for CF11 after April 2019)

  • CF-4204103 - FORM scope is missing values when same named fields include type=file
  • CF-4204102 - sameFormFieldAsArray setting doesn't work with enctype="multipart/form-data"

After some testing, I've concluded it's a ColdFusion bug.

Issue:

The issue seems to occur under these conditions

  • Request is a multipart/form-data POST
  • Contains multiple fields with the same name
  • At least 1 of those fields is a file field i.e. type="file"
  • The first field submitted (within the group) is NOT a file field

Under those conditions, ColdFusion seems to ignore everything before the first file field. (If you check the filepond source ut confirms the metadata field is submitted before any file fields). That's why the metadata value doesn't appear when dumping the FORM scope.

Note, the this.sameFormFieldsAsArray setting has no effect because it doesn't work with multipart/form-data requests.

Test Case

Below is a test case. Notice the results are what you'd expect when the same named field occurs after the first file field?

Screenshot of Test Case

<cfdump var="#form#" label="Form scope">

<form method="post" enctype="multipart/form-data">
    <br>First:
    <input type="file" name="fileFirst"><br>
    <input type="text" name="fileFirst" value="Lions"><br>

    <br>Last:
    <input type="text" name="fileLast" value="Tigers"><br>
    <input type="file" name="fileLast"><br>

    <br>Middle:
    <input type="text" name="fileMiddle" value="Bears"><br>
    <input type="file" name="fileMiddle"><br>
    <input type="text" name="fileMiddle" value="Oh My"><br>

    <input type="submit">
</form>

Workaround

This blog provides a workaround using an undocumented feature of the FORM scope. Using form.getPartsArray() provides access to both "filePond" fields allowing you to extract the value of the dropped field. Not ideal, but does work until the issue is fixed.

Keep in mind this is an undocumented feature, so be sure to isolate the code for easier alterations in case Adobe alters or removes that function in the future (which they've done before, so fair warning!).

<cfscript>
    // dump raw form fields 
    for (part in form.getPartsArray()) {
        writeDump({ fieldName = part.getName()
                    , isFile  = part.isFile()
                    , fieldValue = (part.isFile() ? part.getFileName() : part.getStringValue())
                }
        );
    }
</cfscript>
SOS
  • 6,430
  • 2
  • 11
  • 29
  • Thanks for taking the time to test the bug, the workaround, and to document this so well! If there are any ideas for a better title for this question, I'm all ears. – Michael Mar 14 '19 at 17:25