[jquery] jQuery AJAX single file upload

I know this question has been asked a lot, and I tried at least 10 different codes to run this without success.

I'm trying to upload a single file with jQuery.ajax(), but it doesn't work. The code below always outputs:

please choose a file' because the file's name is not set or something


HTML

<form enctype="multipart/form-data">
  <input name="file" type="file" />
  <input type="button" value="Upload" />
</form>
<div id="result"></div>

jQuery

$(function(){
  $(document).ready(function(){
    var files;

    $('input[type=file]').on('change', prepareUpload);
    function prepareUpload(event){
      files = event.target.files;
    };
    $(':button').click(function(){
        var formData = new FormData();
        $.each(files, function(key, value){
          formData.append(key, value);
        });
        alert(formData);
        $.ajax({
          url: 'check.php',  
          type: 'GET',
          data: formData,
          success: function(data){ $('#result').html(data); }, 
          cache: false,
          contentType: false,
          processData: false
        });
    });
  });
});

PHP

if(isset($_GET['file'])){
    $filename = $_FILES['file']['name'];
    if(isset($filename) && !empty($filename)){
        echo 'sup my man?!';
    }else{
        echo 'please choose a file';
    }
}else{
    echo 'not set';
}

I don't know what the problem is, I know it's in the FormData object creation because the alert - good to go, doesn't work.

BTW it is really important for me that it would be written in jQuery.

This question is related to jquery

The answer is


A. Grab file data from the file field

The first thing to do is bind a function to the change event on your file field and a function for grabbing the file data:

// Variable to store your files
var files;

// Add events
$('input[type=file]').on('change', prepareUpload);

// Grab the files and set them to our variable
function prepareUpload(event)
{
  files = event.target.files;
}

This saves the file data to a file variable for later use.

B. Handle the file upload on submit

When the form is submitted you need to handle the file upload in its own AJAX request. Add the following binding and function:

$('form').on('submit', uploadFiles);

// Catch the form submit and upload the files
function uploadFiles(event)
{
  event.stopPropagation(); // Stop stuff happening
    event.preventDefault(); // Totally stop stuff happening

// START A LOADING SPINNER HERE

// Create a formdata object and add the files
var data = new FormData();
$.each(files, function(key, value)
{
    data.append(key, value);
});

$.ajax({
    url: 'submit.php?files',
    type: 'POST',
    data: data,
    cache: false,
    dataType: 'json',
    processData: false, // Don't process the files
    contentType: false, // Set content type to false as jQuery will tell the server its a query string request
    success: function(data, textStatus, jqXHR)
    {
        if(typeof data.error === 'undefined')
        {
            // Success so call function to process the form
            submitForm(event, data);
        }
        else
        {
            // Handle errors here
            console.log('ERRORS: ' + data.error);
        }
    },
    error: function(jqXHR, textStatus, errorThrown)
    {
        // Handle errors here
        console.log('ERRORS: ' + textStatus);
        // STOP LOADING SPINNER
    }
});
}

What this function does is create a new formData object and appends each file to it. It then passes that data as a request to the server. 2 attributes need to be set to false:

  • processData - Because jQuery will convert the files arrays into strings and the server can't pick it up.
  • contentType - Set this to false because jQuery defaults to application/x-www-form-urlencoded and doesn't send the files. Also setting it to multipart/form-data doesn't seem to work either.

C. Upload the files

Quick and dirty php script to upload the files and pass back some info:

<?php // You need to add server side validation and better error handling here

$data = array();

if(isset($_GET['files']))
{  
$error = false;
$files = array();

$uploaddir = './uploads/';
foreach($_FILES as $file)
{
    if(move_uploaded_file($file['tmp_name'], $uploaddir .basename($file['name'])))
    {
        $files[] = $uploaddir .$file['name'];
    }
    else
    {
        $error = true;
    }
}
$data = ($error) ? array('error' => 'There was an error uploading your files') : array('files' => $files);
}
else
{
    $data = array('success' => 'Form was submitted', 'formData' => $_POST);
}

echo json_encode($data);

?>

IMP: Don't use this, write your own.

D. Handle the form submit

The success method of the upload function passes the data sent back from the server to the submit function. You can then pass that to the server as part of your post:

function submitForm(event, data)
{
  // Create a jQuery object from the form
$form = $(event.target);

// Serialize the form data
var formData = $form.serialize();

// You should sterilise the file names
$.each(data.files, function(key, value)
{
    formData = formData + '&filenames[]=' + value;
});

$.ajax({
    url: 'submit.php',
    type: 'POST',
    data: formData,
    cache: false,
    dataType: 'json',
    success: function(data, textStatus, jqXHR)
    {
        if(typeof data.error === 'undefined')
        {
            // Success so call function to process the form
            console.log('SUCCESS: ' + data.success);
        }
        else
        {
            // Handle errors here
            console.log('ERRORS: ' + data.error);
        }
    },
    error: function(jqXHR, textStatus, errorThrown)
    {
        // Handle errors here
        console.log('ERRORS: ' + textStatus);
    },
    complete: function()
    {
        // STOP LOADING SPINNER
    }
});
}

Final note

This script is an example only, you'll need to handle both server and client side validation and some way to notify users that the file upload is happening. I made a project for it on Github if you want to see it working.

Referenced From


After hours of searching and looking for answer, finally I made it!!!!! Code is below :))))

HTML:

<form id="fileinfo" enctype="multipart/form-data" method="post" name="fileinfo">
    <label>File to stash:</label>
    <input type="file" name="file" required />
</form>
<input type="button" value="Stash the file!"></input>
<div id="output"></div>

jQuery:

$(function(){
    $('#uploadBTN').on('click', function(){ 
        var fd = new FormData($("#fileinfo"));
        //fd.append("CustomField", "This is some extra data");
        $.ajax({
            url: 'upload.php',  
            type: 'POST',
            data: fd,
            success:function(data){
                $('#output').html(data);
            },
            cache: false,
            contentType: false,
            processData: false
        });
    });
});

In the upload.php file you can access the data passed with $_FILES['file'].

Thanks everyone for trying to help:)

I took the answer from here (with some changes) MDN