AJAX file upload with progress bar – Javascript, PHP

There are 2 types of progress bars, one with infinite progress loop similar to this:

and one which shows the number of percentage completed like this:

We will be using the 2nd progress bar as it is more accurate than the first one.

We will be using an AJAX function to upload user selected file on the server and show the progress bar of how much the file has been uploaded. We will be creating just 2 files, 1 for client (index.php) and 1 for server (upload.php). So, start off by creating a simple HTML form in file index.php:

<form method="POST" enctype="multipart/form-data" onsubmit="return onSubmit();">
    <input type="file" name="file" id="file" />
    <input type="submit" name="submit" />
</form>
  • enctype=”multipart/form-data” and method=”POST” are important in <form> tag to upload file.

In order to upload file via AJAX, first we need to stop the default form action method. We can do this by return false from onsubmit attribute of <form> tag. All the code written in this tutorial is pure Javascript, there is no dependency of jQuery in this tutorial.

<script>
    function onSubmit() {
        return false;
    }
</script>

Now, you have to get the user selected file and save it in a variable called file. document.getElementById(“file”) helps in getting the input type file object and it has an array of user selected files in a variable called files.

function onSubmit() {
    var file = document.getElementById("file").files[0];
    return false;
}

To call an AJAX to upload the file, first create an built-in XMLHttpRequest object and save in variable ajax. This object is supported in all browsers and it is native Javascript object, no jQuery is required.

var ajax = new XMLHttpRequest();

Now call open(method, url, async) function from ajax object.

  • First parameter is the method of request GET or POST.
  • Second is the name of PHP file which will upload the file. In this case upload.php which will be created in next step.
  • Third is a boolean, whether the request is asynchronous or not. true for asynchronous. Asynchronous requests does not hang up the browser. Syncronized requests may block the browser if the script at upload.php is very time-taking.
ajax.open("POST", "upload.php", true);

Sending file via AJAX required an FormData object to be appended in the AJAX request. We can create a FormData object simply by the following line:

var formData = new FormData();
formData.append("file", file);
  • formData.append 1st parameter is the string which will used in upload.php file to upload the file and 2nd parameter is the user selected file. In this case, it is stored in variable file

Call the send() function from ajax object to actually call an AJAX request. It accepts 1 parameter that is of FormData object.

ajax.send(formData);

ajax object has multiple functions that are called once the status of request is changed. For example, when server receives the request, if server does not exists, if server failed to respond etc. All these callbacks are received in a function called onreadystatechange.

ajax.onreadystatechange = function() {
    //
};

Now we have to respond only if the request is successful. In this onreadystatechange function, we have 3 variables readyState, status and responseText.

  • readyState will have value 4 when the request is done/completed.
  • status will have value 200 when everything goes right.
ajax.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
    	console.log(this.responseText);
    }
};

Now create a new file named upload.php and open it in code editor. In this file, we will just be storing the file in a server. Paste the following code in upload.php file:

<?php
    move_uploaded_file($_FILES["file"]["tmp_name"], $_FILES["file"]["name"]);
    echo "Done";
?>

At this point if you run the index.php file, you will be able to select a file and save it in your server and your index.php will look like this:

<form method="POST" enctype="multipart/form-data" onsubmit="return onSubmit();">
    <input type="file" name="file" id="file" />
    <input type="submit" name="submit" />
</form>

<script>
    function onSubmit() {
        var file = document.getElementById("file").files[0];

        var formData = new FormData();
        formData.append("file", file);
        
        var ajax = new XMLHttpRequest();
        ajax.open("POST", "upload.php", true);
        ajax.send(formData);

        ajax.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                console.log(this.responseText);
            }
        };

        return false;
    }
</script>

And your upload.php should look like this:

<?php
    move_uploaded_file($_FILES["file"]["tmp_name"], $_FILES["file"]["name"]);
    echo "Done";
?>

Now, in order to view the progress bar you can simply create an <progress> tag anywhere in your index.php where you want to see the progress. Provide it a unique id and set it’s initial value to 0:

<progress id="progress" value="0"></progress>

Get progress bar object in javascript, right above return false; line in the function onSubmit(), like this:

function onSubmit() {
    ..........

    ajax.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            console.log(this.responseText);
        }
    };

    var progress = document.getElementById("progress");
    return false;
}

While uploading files, ajax object also has an event called onprogress that will tell the current uploaded file percentage:

ajax.upload.onprogress = function (event) {
    //
};
  • event variable will tell the current status of uploaded file.

First you have to set the maximum value of progress object to that required by an AJAX request to upload the file:

progress.max = event.total;

Now simply set the progress value attribute to uploaded value from event object:

progress.value = event.loaded;

Now, you will be able to view the progress of an uploaded file via AJAX. Here is a complete code of your index.php file:

<form method="POST" enctype="multipart/form-data" onsubmit="return onSubmit();">
    <input type="file" name="file" id="file" />
    <input type="submit" name="submit" />
</form>

<progress id="progress" value="0"></progress>

<script>
    function onSubmit() {
        var file = document.getElementById("file").files[0];

        var formData = new FormData();
        formData.append("file", file);
        
        var ajax = new XMLHttpRequest();
        ajax.open("POST", "upload.php", true);
        ajax.send(formData);

        ajax.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                console.log(this.responseText);
            }
        };

        var progress = document.getElementById("progress");
        ajax.upload.onprogress = function (event) {
            progress.max = event.total;
            progress.value = event.loaded;
        };

        return false;
    }
</script>

One Reply to “AJAX file upload with progress bar – Javascript, PHP”

Leave a Reply

Please disable your adblocker or whitelist this site!