Upload multiple files via ajax from an HTML file input

It’s because you’re logged out and the code does not handle that

There is also a major security hole in the code, scroll down to see the details

HTTP 400 and a 0 is what admin-ajax.php returns when it cannot find a handler for your AJAX request.

Note that if you had used the modern REST API instead of the legacy admin-ajax.php API it would have told you this in plaintext human readable language and a 404 like this:

{"code":"rest_no_route","message":"No route was found matching the URL and request method.","data":{"status":404}}

It would also have responded with a 403 forbidden if you’d made the same mistake, which is much harder to make when using AJAX with a REST API endpoint

If we look at the tutorial we can see where it adds the AJAX handler action:

add_action('wp_ajax_cvf_upload_files', 'cvf_upload_files');
add_action('wp_ajax_nopriv_cvf_upload_files', 'cvf_upload_files'); // Allow front-end submission

But, if we look at the code in your question:

add_action('wp_ajax_file_upload','file_upload');

Your code has 1 action, the tutorial has 2. You’re missing the wp_ajax_nopriv_ version.

Overrall, keep in mind this is an 8 year old tutorial from 2015, and you shouldn’t follow just a single tutorial when researching things. The official WordPress developer docs explain this much better, and since that tutorial was written a new modern API for AJAX called the REST API was written.

Further Notes

  • you never checked that move_uploaded_file worked or not, it returns a false value if it failed, you need to check for this or it will fail silently and you’ll be scratching your head trying to figure out why files are missing
  • it needs to create the folder!
  • you should not assume the location of the upload folder, the tutorial you shared uses wp_upload_dir() instead of assuming /wp-content/uploads to do this
  • What if $_POST['application_id'] contained something malicious? e.g. ../? or myapplicationID/and/this/is/a/subfolder?
  • the AJAX happens every time the file input changes, which means if I accidentally pick the wrong file, it’s instantly uploaded and I can’t get it back! What if I picked something confidential by accident that was next to it and now we’re both in trouble? Or if I select the same file 5 times, now there are 5 copies on your server. What if I accidentally select a 24GB blueray backup file?
    • the tutorial also has a check for this, but your code does not

🚨 A Major Security Problem In The Code 🚨

  • There is no validation on the files, I could use this to upload and run PHP files!!!!
    • the tutorial you’re following uses the wp_check_filetype function to do this
    • I could use your form to submit PHP files that give me total control over your website then just visit example.com/wp-content/supporting-evidence/myapplicationID/hacksite.php, this is very dangerous!
    • at a minimum check the file extensions, WordPress has functions for checking valid filetypes