Upload Progress Bar in PHP
Description: This deliverable will include three files: uploadFiles.html,
progress.php, and uploadHandler.php. The uploadFiles.html is a file
to load the starting
page to ask user for upload file inputs. The page also shows an empty
bar with the maximum combined total file size indicated at the end. Once the user
clicks on the submit button, the progress bar will show the current uploaded file
portion in respect to the allowable upload file size total. The actual uploaded
size is also shown in an indicator below the bar. Progress.php is the file
that handles all the processing at the back-end. Once the upload
is complete, the uploadHandler.php file will display
a message of either an error or an sucessful upload.
Example:This is what my code outputs on these inputs.
This is a starting page for user file inputs, and shows
an empty progress bar.
This page shows an upload progressing bar and uploaded size while uploading.
Files continue uploading, and progress bar continues growing.
Files almost finish uploading.
All the files have been sucessfully uploaded.
UploadFiles.html File
<!--
UploadFiles.html presents the upload form for user input,
and once the user click on the submit button, the
javascript is invoked to connect to the server every
half second for the total size of the temporary uploaded
files. Once the response comes back from the server,
it is parsed to extract the size value, formatted and shown
on the progress bar. The grand total of all the uploading
files is restricted by the server, and it is currently set
to be 60 MB. Once the upload is successful, it transfers to
progress.php page.
Author: Chao Liang
Date: 3/15/2006
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title> Upload Files </title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<style type="text/css">
<!--
.uploadStatus
{
background-color: #FFFFFF;
position: absolute;
left: 50%;
margin-left: -350px;
width: 550px;
height: 40px;
color: #000000;
text-align: left;
font-family: "Trebuchet MS", Arial;
font-size: 12px;
font-weight: bold;
}
-->
</style>
<script language="JavaScript" type="text/JavaScript">
var myInterval; // a global timer object
var totalSize = 0; // total uploaded size sofar
var counter = 0;
/*
This function set up the timer to connect to the
server every half second
*/
function connectToServer()
{
myInterval = window.setInterval("requestInfo()",500);
}
/*
This function creates an xmlHttpRequest object
according to the browser used.
return: created xmlHttpRequest object
*/
function createXMLHttpRequest()
{
var transfer;
if (window.ActiveXObject)
{
transfer = new ActiveXObject('Msxml2.XMLHTTP');
}
else if (window.XMLHttpRequest)
{
transfer = new XMLHttpRequest();
}
return transfer;
}
/*
This function shows the current uploaded total
on a progress bar.
Parameter: subtotal - the current total size uploaded sofar
*/
function updateBar(subtotal)
{
var myBar = document.getElementById('progressBar');
var barWidth = 400 * subtotal / 60000000;
myBar.style.width = barWidth + 'px';
}
/*
This function formats the bytes into 'KB' and 'MB'
according to their value. It inclues a tenth and handredth
digits if it is formatted into 'KB' or 'MB'.
Parameter: bytes - the total size in bytes
Return: A string corresponds to the passed-in parameter
in 'bytes', 'KB', or 'MB' and 'Bytes', 'KB', or
'MB' included at the end of this string.
*/
function bytesFormatter(bytes)
{
if (bytes < 1024)
return bytes + " Bytes";
if (bytes >=1024 && bytes < (1024 * 1024))
return Math.round(bytes/1024 * 100) / 100 + " KB";
return Math.round(bytes/1024/1024*100) / 100 + " MB";
}
/*
This function parse the return response from the server
to extract the size of the total uploaded files sofar.
Parameter: res - the response come back from server
return: A subtotal of size of uploaded files sofar
*/
function parseResponse(res)
{
var firstIndex = res.indexOf("subtotal:");
if (firstIndex != -1)
{
var retTotal = res.substring(firstIndex+9);
var subSize = parseInt(retTotal);
return subSize;
}
else
return 0;
}
/*
This function sends request to the server, and register
the callback function to process the response when result
comes back from the server.
*/
function requestInfo()
{
var xmlHttpObject;
xmlHttpObject = createXMLHttpRequest();
xmlHttpObject.open("get", "progress.php?id=" + counter, true);
// callback function
xmlHttpObject.onreadystatechange = function ()
{
// The response is stable for process when readyState is 4
if (xmlHttpObject.readyState == 4)
{
// check if upload is successful or not
if (xmlHttpObject.status == 200)
{
var response = xmlHttpObject.responseText;
var subTotal = parseResponse(response);
if (subTotal >= totalSize)
{
var formatedBytes =
bytesFormatter(subTotal);
updateBar(subTotal);
displayInfo(formatedBytes);
totalSize = subTotal;
}
else
setIntervalOut(); // upload has finished
return true;
}
else
{
displayInfo("An error occurred: "
+ xmlHttpObject.statusText);
//statusText is not always accurate
setIntervalOut();
return false;
}
}
};
xmlHttpObject.send(null);
}
/*
This function turns the timer off.
*/
function setIntervalOut()
{
if (myInterval != null)
clearInterval(myInterval);
}
/*
This function is used to display the current
uploaded size sofar on the browser
*/
function displayInfo(text)
{
var divInfo = document.getElementById("progressInfo");
divInfo.innerHTML = text;
}
// Turns the timer off if there is an error or a user-abort action
window.onAbort=setIntervalOut;
window.onError=setIntervalOut;
</script>
</head>
<body onunload="setIntervalOut()">
<form action="uploadHandler.php" enctype="multipart/form-data" method="post">
Send these files:<br/>
<input type="hidden" id="maxSize" name="MAX_FILE_SIZE" value="60000000" />
<input type="file" name="myFile[]" size="30"/><br/>
<input type="file" name="myFile[]" size="30"/><br/>
<input type="file" name="myFile[]" size="30"/><br/>
<input type="submit" value="Send File" onclick="return connectToServer();"/>
</form>
<label for="barContainer">
Upload Progress:
</label>
<div id="barContainer"
style="width:400px;height:16px;border-width:1px;border-style:solid;border-color:black">
<div id="progressBar" style="width:0px;height:15px;background-color:green">
</div>
</div>
<div id="sizeLabel" style="padding-left:400px;height:20px;font-weight:bold">
60 MB</div>
<div id="progressInfo" class="uploadStatus"> </div>
</body>
</html>
Progress.php File
<?php
echo '<?xml version="1.0" encoding="iso-8859-1"?>'
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Upload files progress</title>
</head>
<body>
<?php
/*
The progress.php script to get the total size of the temporary
files that store the uploaded data. Since the sizes
of these files are everchanging, this script will
be called to probe these file sizes every half second.
Author: Chao Liang
Date: 3/15/2006
*/
$tempDir = "c:/windows/temp/";
$file1="";
$subTotal=0;
if (is_dir($tempDir))
{
if ($dh = opendir($tempDir))
{
while (($file = readdir($dh)) !== false)
{
// these temporary files all have php prefix
$uploadTempFile = strstr($file, "php");
if (($uploadTempFile != false) && ($file != $file1))
// Make sure the next temporary file is different
// from the previous one
{
global $subTotal;
$file1 = $file;
$fullPath = $tempDir . $file;
$tmpSize = filesize($fullPath);
if ($tmpSize != false)
$subTotal = $tmpSize + $subTotal;
}
}
// attach the string subtotal: to the front to help
// clients to parse the response
echo "subtotal:" . $subTotal;
closedir($dh);
}
}
?>
</body>
</html>
UploadHandler.php File
<?php
echo '<?xml version="1.0" encoding="ISO-8859-1"?>';
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Upload files status</title>
</head>
<body>
<?php
/*
UploadHandler.php is a script that the form upload to.
It checks for all the errors that would happen while files are
uploaded. If files are uploaded successfully, move
the files to the desinated upload directory.
Author: Chao Liang
Date: 3/15/2006
*/
if (!$_REQUEST['MAX_FILE_SIZE']) // Total file size is over the limit
{
echo "Files are too large." . "<br/>";
exit;
}
$uploadDir = 'd:/phpupload/';
foreach($_FILES['myFile']['name'] as $key => $value)
{
if ($value == null)
continue;
$uploadFile = $uploadDir . $value;
// check if the files are fully uploaded
if(is_uploaded_file($_FILES['myFile']['tmp_name'][$key]))
{
if ($_FILES['myFile']['tmp_name'][$key] != null &&
$_FILES['myFile']['error'][$key] == UPLOAD_ERR_OK)
{
if (move_uploaded_file($_FILES['myFile']['tmp_name'][$key],
$uploadFile))
{
echo $value .
" is valid, and was successfully uploaded." .
"<br/>";
}
else
{
echo "Possible file upload attack!" . "<br/>";
}
}
}
}
?>
</body>
</html>
|