logo
post image

2 Ways of AJAX File Upload - FormData and FileReader

A file can be uploaded with jQuery in 2 ways. The first method is implemented using FormData where a multipart/form-data POST request is sent.
The second method is uploading using FileReader where a normal (application/x-www-form-urlencoded) POST request is sent.

Using FormData

This method is commonly used by developers. A FormData object is used in AJAX file uploading.
processData should be set to false so that jQuery does not process parameters into a query string.
contentType should be set to false. When set to false jQuery will convert this POST request into a multipart/form-data POST request.

$("#upload-button").on('click', function() { // validate type of file if(['image/jpeg', 'image/jpg', 'image/png', 'image/gif'].indexOf($("#file-to-upload").get(0).files[0].type) == -1) { alert('Error : Only JPEG, PNG & GIF allowed'); return; } var $data = new FormData(); $data.append('title', 'Sample Photo Title'); $data.append('file', $("#file-to-upload").get(0).files[0]); // processData & contentType should be set to false $.ajax({ type: 'POST', url: 'upload.php', data: $data, success: function(response) { }, error: function(response) { }, processData: false, contentType: false }); });

At the server side you need to validate the type of file and move it to your required directory.

<?php $title = $_POST['title']; // File name $file_name = $_FILES['file']['name']; // File extension $file_type = pathinfo($file_name, PATHINFO_EXTENSION); // Validate type of file if(in_array(strtolower($file_type), [ 'jpeg', 'jpg', 'png', 'gif' ])) { move_uploaded_file($_FILES['file']['tmp_name'], $file_name); } else { echo 'Error : Only JPEG, PNG & GIF allowed'; } ?>

Using FileReader

The file that is to be uploaded is first read through FileReader function, and then the base64 encoded file data is sent as a normal POST request. Base64 encoded data of the file can be found with the help of readAsDataURL method.

$("#upload-button").on('click', function() { // validate type of file if(['image/jpeg', 'image/jpg', 'image/png', 'image/gif'].indexOf($("#file-to-upload").get(0).files[0].type) == -1) { alert('Error : Only JPEG, PNG & GIF allowed'); return; } var reader = new FileReader(); reader.onload = function(){ var $data = { 'title': 'Sample Photo Title', 'file': reader.result }; $.ajax({ type: 'POST', url: 'upload.php', data: $data, success: function(response) { }, error: function(response) { }, }); }; reader.readAsDataURL($("#file-to-upload").get(0).files[0]); });

At the server side first the base64 encoded data is decoded using the base64_decode function. Then the decoded file data is checked for a valid file type using the finfo_buffer function. If the file data is valid, it is saved through file_put_contents.
Please note that it is not possible to get the actual file name in this case. You will have to name it yourself. (If you badly need the actual file name you can pass it as a POST parameter) <?php $title = $_POST['title']; // Decode base64 data list($type, $data) = explode(';', $_POST['file']); list(, $data) = explode(',', $data); $file_data = base64_decode($data); // Get file mime type $finfo = finfo_open(); $file_mime_type = finfo_buffer($finfo, $file_data, FILEINFO_MIME_TYPE); // File extension from mime type if($file_mime_type == 'image/jpeg' || $file_mime_type == 'image/jpg') $file_type = 'jpeg'; else if($file_mime_type == 'image/png') $file_type = 'png'; else if($file_mime_type == 'image/gif') $file_type = 'gif'; else $file_type = 'other'; // Validate type of file if(in_array($file_type, [ 'jpeg', 'png', 'gif' ])) { // Set a unique name to the file and save $file_name = uniqid() . '.' . $file_type; file_put_contents($file_name, $file_data); } else { echo 'Error : Only JPEG, PNG & GIF allowed'; } ?>

Now the question is — why would you use FileReader method over FormData method ? I would really request an expert to comment on this.