jerodestapa
jerodestapa

Reputation: 58

Send Multiple Files to PHP with Jquery and Fetch

I'm building an HTML form using Jquery to send the data to a PHP backend. It is supposed to allow for multiple attachments, which are then sent via fetch. I'm receiving the $_POST fine, but $_FILES only contains the last file selected.

I know this is because the multiple attribute resets every time a new file picker window is opened, but I it to save each file as it is selected. To address this, I'm trying to capture each file in a JS array, appending the array to FormData before it posts to the server.

$(document).ready(function(e){
    // Add input files to array
    $('#inputId').on('change', function(e) {
        fileList.push(fileName[0]);
    });

    // Form submission
    $("#formId").on('submit', function(e){
        e.preventDefault();
        formData = new FormData(this);
        formData.append(fileList);
        url = '../php/submit.php';
        fetch(url, {method: 'POST', body: formData})
            .then(function(response) {
                return response.text();
            })
            .then(function(body){
                console.log(body);
            });
    });
});
<form id="formId" enctype="multipart/form-data" method="POST">
  <div class="ds-row ds-file-upload-container ds-mar-b-2">
    <div class="ds-col-xs-12 ds-col-md-6">
      <label for="inputId" class="ds-button">Choose a file
        <input type="file" class="ds-file-upload" name="upload[]" id="inputId" multiple="multiple">
      </label>
    </div>
  </div>
</form>

As of now, the form is not submitting anything when the submit button is clicked. If I comment out the #inputId onchange event, it works, but of course, it doesn't have all the files included in the FormData.

Upvotes: 1

Views: 1285

Answers (1)

Always Helping
Always Helping

Reputation: 14570

Here is working code for you and tested as well.

You have few issues with formData append. You are not doing any forEach for your file so so when you are sending the fetch request you formData only gets the last file.

To store multiple file you need to have an empty array which i have named as filesToUpload

This array will store all the file which you will select on change function.

Once the array contains all the files you want to upload. On form submit function you will loop through that filesToUpload array and append all its data to formData and send it via fetch request.

On the backend PHP side when you var_dump($_POST) OR var_dump($_FILES) you will see all these files there.

Working fiddle Demo: https://jsfiddle.net/woft6grd/

In the demo when you go dev tools -> network you will see on form submit your request will have all the files you uploaded via input.

jQuery

$(document).ready(function() {

  // Add input files to array
  var filesToUpload = []

  //On Change loop through all file and push to array[]
  $('#inputId').on('change', function(e) {
    for (var i = 0; i < this.files.length; i++) {
      filesToUpload.push(this.files[i]);
    }
  });

  // Form submission
  $("#formId").on('submit', function(e) {
    e.preventDefault();

    //Store form Data
    var formData = new FormData()
    //Loop through array of file and append form Data
    for (var i = 0; i < filesToUpload.length; i++) {
      var file = filesToUpload[i]
      formData.append("uploaded_files[]", file);
    }

    //Fetch Request
    url = '../php/submit.php';
    fetch(url, {
        method: 'POST',
        body: formData
      })
      .then(function(response) {
        return response.text();
      })
      .then(function(body) {
        console.log(body);
      });
  })
});

HTML

<form id="formId" enctype="multipart/form-data" method="POST">
  <div class="ds-row ds-file-upload-container ds-mar-b-2">
    <div class="ds-col-xs-12 ds-col-md-6">
      <label for="inputId" class="ds-button">Choose a file
        <input type="file" class="ds-file-upload" name="upload[]" id="inputId" multiple="multiple" required>
      </label>
    </div>
  </div>
  <input type="submit" value="Upload" />
</form>

I have added comments to each code line as well to highlight as well.

Upvotes: 2

Related Questions