0

I have a form that passes various types of input to an ajax call, which opens a php script. The script will do various things including processing the file, before echoing an array of variables. All inputs go through $_POST regularly, and the file data is passed, too, but the file itself is not accessible from $_FILES.

I am not using jQuery, so most posts are hard to translate to my case. I have seen a similar issue here,https://stackoverflow.com/questions/56878395/files-empty-after-ajax-upload but that solution doesn't seem to apply.

Here are the key excerpts from the code, thank you in advance for any tips!

var ajaxResponse = "";
var qForm = document.getElementById('myForm');
qForm.addEventListener("submit", function(e) {
  e.preventDefault();
  var formData = new FormData(qForm);
  checkForm(formData);
  console.log(ajaxResponse); //this shows the $_FILES var_dump
});

function checkForm(formData) {
  var vars = "startDate=" + formData.get('startDate') +
    "&qInvited=" + formData.get('qInvited');
  ajaxRequestReturn("checkForm.php", vars);
}


function ajaxRequestReturn(phpRequest, vars) {
  var req = new XMLHttpRequest();
  req.open("POST", phpRequest, false); //not asynchronous, because I pass results to a global variable
  req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); //removing the setRequestHeader doesn't seem to make any difference.
  req.onload = function() {
    ajaxResponse = this.responseText;
  }
  req.onerror = function() {
    throw new Error("Bad request.");
  }
  req.send(vars);
  // form.submit();
}
<form class="loginForm" id="myForm" method="post" enctype="multipart/form-data" action="thisPage.php">
  <div>
    <input type="date" id="startDateInput" name="startDate">
  </div>

  <div>
    <input type="file" name="qInvited" required>
  </div>

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

and the checkForm.php file is currently simply:

<?php
echo var_dump($_FILES);
?>

the var_dump($_FILES) should show the qInvited file in it, but it prints

array(0) {
}

instead.

mplungjan
  • 169,008
  • 28
  • 173
  • 236
dan
  • 11
  • 2
  • Since you're uploading files via AJAX, you should probably use `FormData()`. – FiddlingAway Jan 28 '23 at 13:27
  • He is but not in a transparent manner `var formData = new FormData(qForm);` I suggest you look at other examples and have only ONE function handling the form. Right now it is not clear if you actually send the formdata to the server - I suspect the `checkForm` is not doing what you think it is doing – mplungjan Jan 28 '23 at 13:29
  • 1
    `checkForm()` transforms your data into some sort of query string (as well as your file). Why don't you directly send your object? – Cid Jan 28 '23 at 13:29
  • [More examples](https://www.google.com/search?q=fetch+upload+file+to+php+site%3Astackoverflow.com) – mplungjan Jan 28 '23 at 13:31

1 Answers1

0

To upload a file via ajax you have to pass a FormData object in your call to XMLHttpRequest.send.
Get rid of the checkForm function and call ajaxRequestReturn with formData as the second parameter.
Also, application/x-www-form-urlencoded is not the correct content type(its multipart/form-data), remove that line. The correct content type will be set automatically when you use the FormData object.

Musa
  • 96,336
  • 17
  • 118
  • 137
  • Brilliant, it solved it in one go! I had started with the formData as argument, but it wouldn't work due to - I now understand - the wrong content type header in the ajax request, similar to the analogous question I was citing. Instead, I had first tried to simplify by using the checkForm function, and at that point removing the content header no longer was solving it. In short, I got tangled up in my own web of wrong fixes. Thank you all for the comments! – dan Jan 28 '23 at 20:56