HTML5 Uploading with Progress Bar
With new web technologies such as CSS3, HTML5 and JavaScript updates the new web possibilities are endless. One thing that a lot of sites incorporated now are the ability to drag and drop files to upload them. Below is how to create a simple AJAX file upload with progress bar.
First we have the HTML webpage, this can be nearly everything since we are using the body tag to capture the files.
<html>
<head>
<title>Image Upload</title>
<script src="image.js"></script>
<link type="text/css" rel="stylesheet" href="style.css" />
</head>
<body>
Drag Files Anywhere Here
<div id="process"></div>
</body>
</html>
Now we will make a simple stylesheet to give just a little color to the design and to create the progress bar for the image upload.
.progressbar {
border: 1px solid black;
height: 5px;
width: 500px;
margin-top: 7px;
float: right;
}
.progressbar div {
height: 5px;
width: 0px;
background-color: #0000ff;
}
We have to create the JavaScript to handle the dropped files, send the files to the server, show progress and more.
/*
Wait for window to finish loading, then set event listeners for the body to procress the events
*/
window.onload = function() {
var files = null;
window.addEventListener('drop',dropEvent,false);
window.addEventListener('drageneter',preventEvent,false);
window.addEventListener('dragleave',preventEvent,false);
window.addEventListener('dragover',preventEvent,false);
}
/*
Stop Browser from Navigating to File / Default Handeling
*/
function preventEvent(e) {
e.stopPropagation();
e.preventDefault();
return false;
}
/*
When a file is dropped into the browser, the "drop" event listener points to this function.
*/
function dropEvent(e) {
preventEvent(e);
// Save all dropped files to global variable "files"
files = e.dataTransfer.files;
// Check if files were really dropped or not
if(files.length > 0) {
// Build an output display to show progress
var output = '';
var bg = null;
for(var i = 0; i < files.length; i++) {
if(bg == 'background-color:#ffffff;')
bg = 'background-color:#bbbbbb;'
else
bg = 'background-color:#ffffff;';
output += '<div style="height:20px;' + bg + '"><div style="float:left"><strong>' + escape(files[i].name) + '</strong></div><div class="progressbar"><div id="progress-child-' + i + '"></div></div><div style="clear:both"></div></div>';
}
document.getElementById('process').innerHTML = output;
// Call function to upload files, starting at File[0]
setTimeout(function(){uploadFiles(0);},100);
}
return false;
}
function uploadFiles(i) {
var req = new XMLHttpRequest();
var formdata = new FormData();
req.upload.onprogress = function(e) {
document.getElementById('progress-child-' + i).style.width = (e.position * 100 / e.totalSize) + '%';
}
req.onreadystatechange = function() {
if(req.readyState == 4) {
// Set Progress to 100% when finished
document.getElementById('progress-child-' + i).style.width = '100%';
if(req.status != 200) {
// Turn Progress Red if Error
document.getElementById('progress-child-' + i).style.backgroundColor = "#ff0000";
}
++i;
// If more files, upload the next one
if(i < files.length) {
uploadFiles(i);
}else{
// After all uploads, refresh page
//window.location.href=window.location.href;
}
}
}
// Create form data for the image so the PHP file can progress it
formdata.append("image", files[i]);
req.open("POST","upload.php",true);
req.send(formdata);
}
Last of all we need to create the server code to handle the file uploads. Since this code depends a lot on what you are uploading we are just going to do a very simple image upload that may not have the best security settings and functions in place.
<?php
$success = false;
$error = false;
// Check if uploaded file and not a system file or other file
if(isset($_FILES['image']) && is_uploaded_file($_FILES['image']['tmp_name']) && $_FILES['image']['error'] == 0) {
if(!is_dir('uploads')) {
mkdir('uploads');
}
// Sets the filename to a unique ID
$filename = 'uploads/'.uniqid().'.jpg';
// Check the image type and create image from GD using that type
switch(exif_imagetype($_FILES['image']['tmp_name'])) {
case 1:
$img = imagecreatefromgif($_FILES['image']['tmp_name']);
break;
case 2:
$img = imagecreatefromjpeg($_FILES['image']['tmp_name']);
break;
case 3:
$img = imagecreatefrompng($_FILES['image']['tmp_name']);
break;
default:
$error = true;
break;
}
if($error == false) {
// Convert image to jpeg and save to new location
$success = imagejpeg($img, $filename, 100);
imagedestroy($img);
if($success) {
// Successful Image name is $filename
}
}
}
if($success == false) {
// Not Successful - should return error
header("HTTP/1.1 500 Internal Server Error");
}