HTML5 Uploading with Progress Bar

GeekThis happily runs on Vultr. Get $300 of free hosting credits to try out their cloud compute, kubernetes engine, or managed databases. Try Vultr today to claim your free $300.

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");
	}

Related Posts

JavaScript Tag Cloud

Learn how to create a tag cloud using only JavaScript along with sample code to use.

HTML5 Game Development Basics

Learn how to get started with creating games using HTML5 and JavaScript without any libraries.

How JSON P Works With Library

Learn how JSONp works along with sample JavaScript to perform a JSONP request.

Adding PHP to your HTML and CSS Blog

Learn how to create a simple PHP Blog in a matter of minutes.