0

So I have a simple FormData object with which I am trying to upload a File, without having to do form submit. In HTML I have created a simple form with 1) a File Upload 2) another simple text input for proof of concept. Trying to use the jquery $.post function to achieve this. The PHP file PHP_SIMPLE_AJAX_IMAGE.php just spits back the data from the same sent image. HTML is::

<form id="form_image_upload">
    <input type="file" id="input_file" name="input_file_n"></input>
    <label for="input_file" id="label_input_file" >choose file</label>
    <label for="input_file" id="label_small_input_file">...</label><br>
    
    <input type="text" id='simp_text_id' name='simp_text_n' ><br>
    <button id="btn_submit" type="submit" value="submit" class="upload_file">Submit</button>
<form>

<DIV id="Sub_Div_7"> </DIV>

Javascript

$("#input_file").change(function(e){
    $("#label_small_input_file").html(e.target.files[0].name);
    });

$("#form_image_upload").submit(function(e){
        e.preventDefault();
        let fd = new FormData(this);
    //  alert( fd.get('input_file_n').name);  //This works
    //  alert( fd.get('simp_text_n'));  //This works
        
    $.post("PHP/PHP_SIMPLE_AJAX_IMAGE.php", fd, function(data){ 
                            $("#Sub_Div_7").html(data); });
});

PHP

<?PHP 
if(isset($_FILES['input_file_n'])
{       $F_name = $_FILES['input_file_n']['name'];
        $F_tmpnm = $_FILES['input_file_n']['tmp_name'];
        $F_type = $_FILES['input_file_n']['type'];
        $F_size = $_FILES['input_file_n']['size'];      }

$text_1 = isset($_POST['simp_text_n']) ? $_POST['simp_text_n'] : "NULL";
echo "Filename: " . $F_name . " Tempname: " . $F_tmpnm . " Type: ". $F_type  . " Size: " . $F_size . " TextInput: " . $text_1 ;
?>

When I put the two lines alert( fd.get('input_file_n').name); alert( fd.get('simp_text_n')); I get the alerts with the correct filename, so the fd object is indeed grabbing onto the form data. however when I execute, in the console I get a big error.. something along the lines of: "Uncaught TypeError: Illegal invocation" at the line in the javascript where $.post(... ) is located.. what is wrong?

JS Error

Madventures
  • 119
  • 8
  • Does this answer your question? [How to send FormData objects with Ajax-requests in jQuery?](https://stackoverflow.com/questions/6974684/how-to-send-formdata-objects-with-ajax-requests-in-jquery) – Robin Zigmond Aug 30 '20 at 11:25
  • The short answer is that you cannot pass a `FormData` object; jQuery only allows plain objects or strings by default. See here: https://stackoverflow.com/questions/166221/how-can-i-upload-files-asynchronously My recommendation is to use `fetch()` instead. –  Aug 30 '20 at 11:27
  • You still need a solution to this ? – Always Helping Aug 30 '20 at 11:56
  • @AlwaysHelping yes I still do.. I don't know if using $.ajax is the answer, or using just pure javascript ajax call.. Im not sure what to do.. – Madventures Aug 30 '20 at 11:58
  • 1
    Ideally you want to use `$.ajax` if you are using jQuery. But fetch api can work too. Let me know – Always Helping Aug 30 '20 at 11:59
  • I will try $.ajax, no idea how to use fetch api.. am a bit of a newbie sadly :( let me work out $.ajax, will get back in about 30 mins.. if you are still here – Madventures Aug 30 '20 at 12:01
  • @Madventures No worries. I have added an answer which uses fetch or with ajax below. – Always Helping Aug 30 '20 at 12:07

2 Answers2

3

Follow below instruction:

  1. You should have an input with type file in your html part:
<input type="file" id="file_target">
  1. Add change event for file input
$('#file_target').change(function (e) {
  e.preventDefault();

  // for single file upload
  uploadFile(this.files[0]);

  // for multiple file upload
  $.each(this.files, function (k, file) {
    uploadFile(file);
  });
});
  1. Add uploadFile function that can upload the file:

You can validate the file to be upload here

function uploadFile(file) {
  // some validation like size or dimension
  //...

  var urlPath = 'php_script_file_for_upload';

  // create data to be send
  var fd = new FormData();
  fd.append('file_data', file);
  
  // if you do not want use jQuery
  var xhr = new XMLHttpRequest();
  // third parameter is set to be async request
  xhr.open('POST', urlPath, true);
  xhr.send(fd);

  // if you do use jQuery
  $.ajax({
    method: 'POST',
    url: urlPath,
    data: fd
  });
}
  1. PHP script file
if(!empty($_FILES['file_data']))
  {
  $path = "uploads/";
  $path = $path . basename( $_FILES['file_data']['name']);

  if(move_uploaded_file($_FILES['file_data']['tmp_name'], $path)) {
    // successful upload
  } else{
    // error during upload
  }
}

If you need no ajax approach please see https://gist.github.com/taterbase/2688850

MMDM
  • 465
  • 3
  • 11
  • Thanks a lot @MMDM, it is very clear the solution you suggested. The problem I was having was; while using simple js, between xhr.open() and xhr.send() I had xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'). When I commented that out, it worked very well. Just one more q'n, what are the 'k' and 'file' arguments in your line * $.each(this.files, function (k, file) {..} ;* Im a begineer. Thank you so much! – Madventures Aug 31 '20 at 14:26
  • My pleasure. In jQuery foreach, you can check index and value of an array through first and second arguments. So `k` is the index and `file` is value of it. – MMDM Aug 31 '20 at 16:35
1

You can simply fetch to send do post request to your backend php file.

The reason its not working for you is that $.post cannot handle formData object itself - hence why you are getting that error.

Using fetch with Post method

Live Demo:

$("#input_file").change(function(e) {
  $("#label_small_input_file").html(e.target.files[0].name);
});

$("#form_image_upload").submit(function(e) {
  e.preventDefault();
  let fd = new FormData($(this)[0]) //store data using $(this)[0]

  //Using Simple Fetch API
  fetch('PHP/PHP_SIMPLE_AJAX_IMAGE.php', {
      method: 'post',
      body: fd,
    })
    .then(function(data) {
      $("#Sub_Div_7").html(data);
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="form_image_upload">
  <input type="file" id="input_file" name="input_file_n" />
  <label for="input_file" id="label_input_file">choose file</label>
  <label for="input_file" id="label_small_input_file">...</label><br>

  <input type="text" id='simp_text_id' name='simp_text_n'><br>
  <button id="btn_submit" type="submit" value="submit" class="upload_file">Submit</button>
  <form>

<div id="Sub_Div_7"> </div>

Using $.ajax with post method

Live Demo:

$("#input_file").change(function(e) {
  $("#label_small_input_file").html(e.target.files[0].name);
});

$("#form_image_upload").submit(function(e) {
  e.preventDefault();
  let fd = new FormData($(this)[0])
  $.ajax({
    url: 'PHP/PHP_SIMPLE_AJAX_IMAGE.php',
    type: 'POST',
    data: fd,
    processData: false,
    contentType: false,
    success: function(data) {
      $("#Sub_Div_7").html(data);
    }
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="form_image_upload">
  <input type="file" id="input_file" name="input_file_n" />
  <label for="input_file" id="label_input_file">choose file</label>
  <label for="input_file" id="label_small_input_file">...</label><br>

  <input type="text" id='simp_text_id' name='simp_text_n'><br>
  <button id="btn_submit" type="submit" value="submit" class="upload_file">Submit</button>
  <form>

<div id="Sub_Div_7"> </div>
Always Helping
  • 14,316
  • 4
  • 13
  • 29
  • THanks a lot @AlwaysHelping, yes this works. Your answer is correct, as is the one posted by MMDM. Thank you so much.. and nice bike! I'd buy you a few beers for your help ;) – Madventures Aug 31 '20 at 14:17
  • @Madventures You are welcome. Happy to have helped you. Let me know if there is something you need help with. – Always Helping Aug 31 '20 at 22:04