0

I have a project that involves uploading documents as part of a form in PHP:

function uploadFlight(oForm, cFunction)
{
    // This tries a number of different methods for getting an AJAX object
    // to ensure cross-browser compatibility.
    var ajax=gimmeAjax(); 
    if (ajax == null) return;

    ajax.function=cFunction;
    ajax.oForm=oForm;

    // Disable all inputs
    cItems=oForm.getElementsByTagName('input');
    iItems=cItems.length;
    for (var i = 0; i < iItems; i++)
    {
        cItems[i].disabled=true;
    }

    // ... and selects.
    cItems=oForm.getElementsByTagName('select');
    iItems=cItems.length;
    for (var i = 0; i < iItems; i++)
    {
        cItems[i].disabled=true;
    }

    ajax.onreadystatechange = function()
    {
        // Redacted as not relevant to this question
    }

    var formData = new FormData();

    for (var i = 0; i < oForm.length; i++)
    {
        oElem=oForm.item(i);
        if (oElem.tagName.toLowerCase() == "input" || oElem.tagName.toLowerCase() == "select")
        {
            switch (oElem.name)
            {
                case 'document':
                    formData.append('document', oElem.files[0]);
                    break;
                case 'project':
                case 'flight_direction':
                case 'flight_type':
                    formData.append(oElem.name, oElem.options[oElem.selectedIndex].value);
                    break;
                case 'employee_id[]':
                    formData.append('employee_id[]', oElem.value);
                    break;
                case 'task':
                    if (oElem.submitted == true) formData.append(oElem.name, oElem.value);
                    break;
                default:
                    formData.append(oElem.name, oElem.value);
            }
        }
    }

    ajax.open("POST", "comms_ajax.php?module=flight&ts="+get_epoch(), true);
    ajax.setRequestHeader("Content-type", "multipart/form-data");
    ajax.send(formData);

    return false;
}

In IE11 and Chrome, this works great. In Edge, it returns a litany of errors:

[11-Jul-2017 09:18:31 Australia/Sydney] PHP Warning:  Missing boundary in multipart/form-data POST data in Unknown on line 0
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: flight_date in [REDACTED]\comms_ajax.php on line 37
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: flight_id in [REDACTED]\comms_ajax.php on line 63
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: flight_id in [REDACTED]\comms_ajax.php on line 70
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: flight_id in [REDACTED]\comms_ajax.php on line 77
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: flight_id in [REDACTED]\comms_ajax.php on line 111
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: employee_id in [REDACTED]\comms_ajax.php on line 118
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Warning:  str_repeat(): Second argument has to be greater than or equal to 0 in [REDACTED]\comms_ajax.php on line 118
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: flight_id in [REDACTED]\comms_ajax.php on line 120
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: employee_id in [REDACTED]\comms_ajax.php on line 120
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Warning:  array_merge(): Argument #2 is not an array in [REDACTED]\comms_ajax.php on line 120
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: carrier in [REDACTED]\comms_ajax.php on line 139
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: flight_no in [REDACTED]\comms_ajax.php on line 139
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: depart_time in [REDACTED]\comms_ajax.php on line 140
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: arrive_time in [REDACTED]\comms_ajax.php on line 140
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: checkin_time in [REDACTED]\comms_ajax.php on line 141
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: flight_type in [REDACTED]\comms_ajax.php on line 141
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: notes in [REDACTED]\comms_ajax.php on line 142
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: flight_direction in [REDACTED]\comms_ajax.php on line 142
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: airport in [REDACTED]\comms_ajax.php on line 143
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: project in [REDACTED]\comms_ajax.php on line 144
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: flight_id in [REDACTED]\comms_ajax.php on line 144
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: carrier in [REDACTED]\comms_ajax.php on line 156
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: flight_no in [REDACTED]\comms_ajax.php on line 156
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: depart_time in [REDACTED]\comms_ajax.php on line 156
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: arrive_time in [REDACTED]\comms_ajax.php on line 156
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: checkin_time in [REDACTED]\comms_ajax.php on line 156
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: flight_type in [REDACTED]\comms_ajax.php on line 157
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: notes in [REDACTED]\comms_ajax.php on line 157
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: flight_direction in [REDACTED]\comms_ajax.php on line 157
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: airport in [REDACTED]\comms_ajax.php on line 157
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: project in [REDACTED]\comms_ajax.php on line 157
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: task in [REDACTED]\comms_ajax.php on line 161
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: task in [REDACTED]\comms_ajax.php on line 205
[11-Jul-2017 09:18:32 Australia/Sydney] PHP Notice:  Undefined index: task in [REDACTED]\comms_ajax.php on line 224

Changing the Content-type header to set the boundary takes away the first error (as per https://stackoverflow.com/a/40561831/1817255) but none of the other fields come through. Any ideas?

Aaron Mason
  • 310
  • 3
  • 11
  • 1
    BTW, you can simplify `oElem.options[oElem.selectedIndex].value` to just `oElem.value`. – Barmar Jul 11 '17 at 00:15
  • https://developer.mozilla.org/en-US/docs/Web/API/FormData says that Edge supports `FormData`, so it seems like this should work. – Barmar Jul 11 '17 at 00:19
  • When you open Developer Tools and look at what's sent in the AJAX request, does it show that it's sending all these parameters? – Barmar Jul 11 '17 at 00:20
  • Try adding `console.log()` calls into the `for` loop that adds to the FormData object, to make sure it's finding the inputs properly. – Barmar Jul 11 '17 at 00:21
  • @Barmar thanks for your input, I can see the parameters in the Network tab. The gist I get from others who have this issue is that when you use `setRequestHeaders` to set the multipart/form-data content type, it doesn't add the boundary parameter. Adding one doesn't change the boundary text used, it still generates its own. – Aaron Mason Jul 11 '17 at 02:06
  • My expectation is that you shouldn't need to set the `multipart/form-data` content type explicitly -- when you use `FormData` the browser should send this by default and fill it in with the boundary that it used. I don't see any other way it could work, since there's no way to find out what boundary the browser sends. – Barmar Jul 11 '17 at 18:19
  • Ok, I removed that line and it now works in Edge. Seems one doesn't need to specify that header if files are involved as I was led to believe, at least not for IE, Edge and Chrome. If you want, submit that as an answer and I'll mark it. – Aaron Mason Jul 12 '17 at 05:03

1 Answers1

1

Don't set the content type explicitly, i.e. remove the line

ajax.setRequestHeader("Content-type", "multipart/form-data");

This is the default when the argument to XMLHttpRequest.prototype.send() is a FormData object, and the browser automatically supplies the boundary option that matches what it's using.

Barmar
  • 741,623
  • 53
  • 500
  • 612