42

Ajax File Upload with PHP, HTML5 File API and jQuery

Ajax file uploader is useful web tool, which is actually very easy to create with jQuery and PHP, and with new HTML5 FileReader API support, we can do client side file validation before even uploading the file to server. Today we are going to combine all these web features to make an Ajax based file uploader, which can be easily integrated into any HTML forms.  

Ajax file upload

Upload Form Markup

HTML contains file input field, upload button, progress bar and DIV element to output server responses. Only thing to notice here is “multipart/form-data” attribute, it is a data encoding method available in HTML and we always need to include this attribute in our HTML form tag, when creating file upload forms.

 
1
2
3
4
5
6
7
<form action="processupload.php" method="post" enctype="multipart/form-data" id="MyUploadForm">
<input name="FileInput" id="FileInput" type="file" />
<input type="submit"  id="submit-btn" value="Upload" />
<img src="images/ajax-loader.gif" id="loading-img" style="display:none;" alt="Please Wait"/>
</form>
<div id="progressbox" ><div id="progressbar"></div ><div id="statustxt">0%</div></div>
<div id="output"></div>

jQuery and HTML5 File API

Since we are using jQuery, I’ve included jQuery form plugin in our upload form to make things easier. It offers so many options to manipulate form with minimal code, which is great thing, because we can focus on other things like HTML5 File API. The FileReader is a powerful new feature of HTML5, which lets us read the contents of files locally, validating file is easier than ever. Earlier people used different methods to achieve the same, but it was a daunting task.

We only need these few lines of jQuery code to actually send our file to server using Ajax, with jQuery Form plugin included in our page. No more code is required, but as you can see it also accepts various options such as “beforeSubmit“, “success“, “uploadProgress” etc. (You can find more options here). which can greatly extend the functionality of our form, we can just create block of functions and call them within the option.

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$(document).ready(function() {
var options = {
    target:   '#output',   // target element(s) to be updated with server response
    beforeSubmit:  beforeSubmit,  // pre-submit callback
    success:       afterSuccess,  // post-submit callback
    uploadProgress: OnProgress, //upload progress callback
    resetForm: true        // reset the form after successful submit
};
       
 $('#MyUploadForm').submit(function() {
    $(this).ajaxSubmit(options);           
    return false;
});
});

Checking HTML5 File API Browser support

Let’s write a beforeSubmit function, which will be called before uploading the file to server, and it is our important piece of code here, because we are going to use HTML File API in it, which will validate the file size and type locally. Since more and more browsers now support HTML FileReader, I think we should definitely use it more often in our upload forms.

 
1
2
3
4
5
6
7
8
9
10
11
12
function beforeSubmit(){
   //check whether client browser fully supports all File API
   if (window.File && window.FileReader && window.FileList && window.Blob)
    {

        }
        else
    {
       //Error for older unsupported browsers that doesn't support HTML5 File API
       alert("Please upgrade your browser, because your current browser lacks some new features we need!");
    }
}

Checking File size and type before upload using HTML5 File API

The following code accesses the browser File API support and checks whether the user is trying to upload right file type and its size is under the allowed limit. Older browsers will get an error message asking to upgrade their browser.

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
function beforeSubmit(){
   //check whether client browser fully supports all File API
   if (window.File && window.FileReader && window.FileList && window.Blob)
    {
       var fsize = $('#FileInput')[0].files[0].size; //get file size
           var ftype = $('#FileInput')[0].files[0].type; // get file type
        //allow file types
      switch(ftype)
           {
            case 'image/png':
            case 'image/gif':
            case 'image/jpeg':
            case 'image/pjpeg':
            case 'text/plain':
            case 'text/html':
            case 'application/x-zip-compressed':
            case 'application/pdf':
            case 'application/msword':
            case 'application/vnd.ms-excel':
            case 'video/mp4':
            break;
            default:
             $("#output").html("<b>"+ftype+"</b> Unsupported file type!");
         return false
           }
   
       //Allowed file size is less than 5 MB (1048576 = 1 mb)
       if(fsize>5242880)
       {
         alert("<b>"+fsize +"</b> Too big file! <br />File is too big, it should be less than 5 MB.");
         return false
       }
        }
        else
    {
       //Error for older unsupported browsers that doesn't support HTML5 File API
       alert("Please upgrade your browser, because your current browser lacks some new features we need!");
           return false
    }
}

Progress Bar

It’s always a good idea to include a progress bar in our file uploader to track upload progress, since we are dealing with different files and unlike images, other files can be bigger in size and can take quite a long time to upload. The jQuery form plugin passes several progress information to our function (If supported by browser), which we will capture and use to animate our progress bar.

 
1
2
3
4
5
6
7
8
9
10
11
function OnProgress(event, position, total, percentComplete)
{
    //Progress bar
    $('#progressbox').show();
    $('#progressbar').width(percentComplete + '%') //update progressbar percent complete
    $('#statustxt').html(percentComplete + '%'); //update status text
    if(percentComplete>50)
        {
            $('#statustxt').css('color','#000'); //change status text to white after 50%
        }
}

Server side PHP

Once the file is successfully uploaded to server via the HTTP POST method, we can access the file information using PHP code. The information we need here are file name, type and size, using the information here too we double check for valid file size and type. And then using PHP move_uploaded_file function, we will move the file to a new location, then we can just add mySQL code to store information in the database.

Here’s the complete PHP code which does the server side task, you need to place this file along with upload HTML form page we created earlier, just point your Ajax form to this file.

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php
if(isset($_FILES["FileInput"]) && $_FILES["FileInput"]["error"]== UPLOAD_ERR_OK)
{
    ############ Edit settings ##############
    $UploadDirectory    = '/home/website/file_upload/uploads/'; //specify upload directory ends with / (slash)
    ##########################################
   
    /*
    Note : You will run into errors or blank page if "memory_limit" or "upload_max_filesize" is set to low in "php.ini".
    Open "php.ini" file, and search for "memory_limit" or "upload_max_filesize" limit
    and set them adequately, also check "post_max_size".
    */

   
    //check if this is an ajax request
    if (!isset($_SERVER['HTTP_X_REQUESTED_WITH'])){
        die();
    }
   
   
    //Is file size is less than allowed size.
    if ($_FILES["FileInput"]["size"] > 5242880) {
        die("File size is too big!");
    }
   
    //allowed file type Server side check
    switch(strtolower($_FILES['FileInput']['type']))
        {
            //allowed file types
            case 'image/png':
            case 'image/gif':
            case 'image/jpeg':
            case 'image/pjpeg':
            case 'text/plain':
            case 'text/html': //html file
            case 'application/x-zip-compressed':
            case 'application/pdf':
            case 'application/msword':
            case 'application/vnd.ms-excel':
            case 'video/mp4':
                break;
            default:
                die('Unsupported File!'); //output error
    }
   
    $File_Name          = strtolower($_FILES['FileInput']['name']);
    $File_Ext           = substr($File_Name, strrpos($File_Name, '.')); //get file extention
    $Random_Number      = rand(0, 9999999999); //Random number to be added to name.
    $NewFileName        = $Random_Number.$File_Ext; //new file name
   
    if(move_uploaded_file($_FILES['FileInput']['tmp_name'], $UploadDirectory.$NewFileName ))
       {
        // do other stuff
               die('Success! File Uploaded.');
    }else{
        die('error uploading File!');
    }
   
}
else
{
    die('Something wrong with upload! Is "upload_max_filesize" set correctly?');
}

That’s it, I have tried to make this tutorial very simple, you can download the sample files from below and continue with testing. The demo you’ll see is from different tutorial, but works similar way and it only allows image files. If you have any suggestions please go ahead and leave your valuable comments, good luck!

Download Demo

Related Articles:

Saran Chamling loves the web technology, and enjoys designing, exploring and writing about it @sanwebe.com. You can find him at Twitter, Google or Facebook.

42 Comments Add Comment

    • After move_upload_file you can insert $NewFilename value into any mysql table which have field name for image name .

  1. Hi,
    There, I am getting one issue with PNG images when i am uploading from this code. As it is not preserving the transparency of the image and shows black color in place of it. My image is 32bit transparent PNG.
    Kindly suggest what i am making wrong with it.

    Thanks.

    Add Reply
  2. Hi I have tried your code for upload ten images at same time. but not multiple attribute. that is image processed one by one. Where I have tried ten images some times it does not work. Progress bar stands upto 50 or 70 % itself. Please help me to fix that issue

    Add Reply
  3. Thanks for putting this together. A couple of years ago, I would not have attempted to make such a feature rich upload form. Now it has become super easy. Again, thanks for sharing.

    Add Reply
  4. Hi Saran, I was trying to implement that to my website but when I try your example it doesn’t works,

     
    1
    2
    3
    if (!isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
            die('');
        }

    is always triggered, could you help me please?

    Thanks in advance,

    Add Reply
  5. very nice website keep up with the good work.
    i am in love with the progress bar indicator during upload
    please may i find out if you could assist me with the script?

    Add Reply
  6. This is really good coding.. but i need to ur help. I went to display image instantly then i Upload and save it database and folder…

    Add Reply
  7. Any ideas where the nearing 1mb limit is? I can upload files up to around 1mb and then anything larger it gets kicked – just does not transfer. My php limits are 30mb for post and 100mb for file in the php.ini.

    Add Reply
    • I found it was the PHP processing time limit imposed by my ISP – moved ISP and I got over 30mb a transfer. booo for 1and1

  8. Ok, i found as limit upload :

     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    //connect &amp; insert file record in database
            $dbconn = mysql_connect($MySql_hostname, $MySql_username, $MySql_password)or die("Unable to connect to MySQL");
            mysql_select_db($MySql_databasename,$dbconn);
           
            $re=mysql_query("select * from file_records");
    $n=mysql_num_rows($re);//esto calcula el numero de registros
    // si deseo que se inserten solo 20 por ejemplo

    if($n&lt;2)

           
            @mysql_query(&quot;INSERT INTO file_records (file_name, file_title, file_size, uploaded_date) VALUES (&#039;$NewFileName&#039;, &#039;$FileTitle&#039;,$FileSize,&#039;$uploaded_date&#039;)&quot;);
            mysql_close($dbconn);
           
            if($n&lt;5)
            echo(&#039;Success! File Uploaded.&#039;);
           
     
              else
            die(&#039;Error: Maximo 5 Archivos&#039;);
       
             
       }
    }

    ————————–

    in mysql dont upload, but in folder save the file….. and, too i dont find where limit file size, you know ??

    Add Reply
  9. Hi ! nice script, but, how can i limit the number max to upload…..
    sorry my english is bad… ;)

    but I need for example tha person only can upload 5 file or imagen, how can i do ??

    Add Reply
  10. If you want to avoid error “Make sure Upload directory exist!”:

    Instead:
    if (!@file_exists($UploadDirectory)) {
    //destination folder does not exist
    die(“Make sure Upload directory exist!”);
    }

    Add:
    if(!is_dir($UploadDirectory)) {
    mkdir($UploadDirectory);
    }

    It creates directory for you! ;)

    Add Reply
  11. I’m trying to place two upload buttons on my page.
    But only the first one works with ajax.
    The second button “submit” work with action=”uploader.php”
    Each button has its own form tag “”
    Need Help!

    Add Reply
  12. Warning: mysql_real_escape_string() [function.mysql-real-escape-string]: Access denied for user ‘root’@’localhost’ (using password: NO) in /home/u438617076/public_html/here_upload_stuff/uploader.php on line 39

    Warning: mysql_real_escape_string() [function.mysql-real-escape-string]: A link to the server could not be established in

    Add Reply
  13. Good work!

    1. I can’t see any control for same name existing file, am i wrong?
    2. When i click on submit without title field or file field, i get error in #output and this is right. but also form get reset, so i must re-insert all data…and this isn’t very good for user…how can i fix it?

    Tnk

    Add Reply

 

Use Gravatar for Comment Pic | Start a topic for crucial discussion.


Notify me of followup comments via e-mail. You can also subscribe without commenting.

Go Top ↑