1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > PHP_APC+Ajax实现的监视进度条的文件上传

PHP_APC+Ajax实现的监视进度条的文件上传

时间:2022-05-14 06:44:00

相关推荐

PHP_APC+Ajax实现的监视进度条的文件上传

// load.js:ADS.addEvent(window, 'load', function (event) {var fileList = ADS.$('fileList');// 按照需要修改uoloadFormaddProgressBar('uploadForm', function (response) {var files = response.filesProcessed;for (var i in files) {// 跳过空文件if (files[i] === null) {continue;}// 创建一个新的文件列表元素var li = document.createElement('li');var a = document.createElement('a');a.setAttribute('href', 'uploads/' + files[i]);a.appendChild(document.createTextNode(files[i]));li.appendChild(a);fileList.appendChild(li);}// 更新文件计数器var countContainer = ADS.$('fileCount');ADS.removeChildren(countContainer);var numFiles = fileList.getElementsByTagName('li').length;countContainer.appendChild(document.createTextNode(numFiles));});});// uploader.js:/*** User: lindongpeng* Date: 13-2-19*/function verifyFileType(fileInput) {if (!fileInput.value || !fileInput.accept) {return true;}var extension = fileInput.value.split('.').pop().toLowerCase(),mimetypes = fileInput.accept.toLowerCase().split(','),type;for (var i = 0, len = mimetypes.length; i < len; i++) {type = mimetypes[i].split('/')[1];if (type === extension || (type === 'jpeg' && extension === 'jpg')) {return true;}}return false;}var addProgressBar = function (form, modificationHander) {// 检查表单是否存在if (!(form = ADS.$(form))) {return false;}// 查找所有文件输入元素var allInputs = form.getElementsByTagName('input');var input;var fileInputs = [];for (var i = 0; (input = allInputs[i]); i++) {if (input.getAttribute('type') === 'file') {fileInputs.push(input);}}// 如果没有文件输入元素则停止脚本if (!fileInputs.length) {return false;}// 添加change事件以基于MIME类型验证扩展名for (var j = 0, len = fileInputs[i]; i < len; j++) {// 使用change事件侦听器进行文件类型检查ADS.addEvent(fileInputs[i], 'change', function (event) {var ok = verifyFileType(this);if (!ok) {if (!ADS.hasClassName(this, 'error')) {ADS.addClassName(this, 'error');}alert('Sorru, that file type is not allowed.Please select one of:' + this.accept.toLowerCase());} else {ADS.removeClassName(this, 'error');}});}// 为上传而附加iframe元素// 在IE中,不能像下面这样通过DOM设置name属性,例如:// var uploadTargetFrame = document.createElement('iframe');// uploadTargetFrame.setAttribute('id', 'uploadTargetFrame');// uploadTargetFrame.setAttribute('name', 'uploadTargetFrame');// 为解决这个问题,需要创建一个div并使用其innerHTML属性// 从而确保在IE和其他浏览器中都能正确的设置name属性var uploadTargetFrame = document.createElement('div');uploadTargetFrame.innerHTML = '<iframe name="uploadTargetFrame" id="uploadTargetFrame"></iframe>';ADS.setStyleById(uploadTargetFrame, {'width': 0,'height': 0,'border': 0,'visibility': 'hidden','z-index': -1});document.body.appendChild(uploadTargetFrame);// 将表单的target属性修改为新iframe元素// 这样可以避免页面重载form.setAttribute('target', 'uploadTargetFrame');// 创建一个唯一的ID以跟踪上传进度var uniqueID = 'A' + Math.floor(Math.random() * 1000000000000000);// 为APC_UPLOAD_PROGRESS键添加这个唯一ID// 这个字段必须添加到文件输入字段之前,以便// 服务器首先取得改键并触发存储进度信息的操作var uniqueIDField = document.createElement('input');uniqueIDField.setAttribute('type', 'hidden');uniqueIDField.setAttribute('value', uniqueID);uniqueIDField.setAttribute('name', 'APC_UPLOAD_PROGRESS');form.insertBefore(uniqueIDField, form.firstChild);// 创建进度条的不同部分// 进度条var progressBar = document.createElement('div');progressBar.className = 'progressBar';// 内部的背景容器var progressBackground = document.createElement('div');progressBackground.className = 'progressBackground';ADS.setStyle(progressBackground, {'height': '10px'});progressBackground.appendChild(progressBar);// 检查已有的定位点// 必须是带有progressContainer类的span元素var progressContainer = ADS.getElementsByClassName('progressContainer','div')[0];// 如果该定位点不存在则创建一个并将其添加到表单中if (!progressContainer) {progressContainer = document.createElement('div');progressContainer.className = 'progressContainer';form.appendChild(progressContainer);}// 添加进度条的其余部分 progressContainer.appendChild(progressBackground);// 同时也添加一个进度信息显示区域var progressMessage = document.createElement('div');progressMessage.className = 'progressMessage';progressContainer.appendChild(progressMessage);// 创建一个将由后面的进度监视方法使用// 的私有方法,以方便更新进度条和相应信息function updateProgressBar(percent, message, satus) {progressMessage.innerHTML = message;ADS.removeClassName(progressMessage, 'error complete waiting uploading');ADS.addClassName(progressMessage, satus);// CSS样式和className将负责指示状态 ADS.setStyle(progressBar, {'width': percent});}// 从0%和waiting开始初始化进度条updateProgressBar('0%', 'Waiting for upload', 'waiting');// 为表单添加提交事件侦听器,用于// 验证表单信息和更新进度条ADS.addEvent(form, 'submit', function (event) {// 再次检查输入以确保// 其包含正确的扩展名var ok = true;var hasFiles = false;for (var i = 0, fileInput; (fileInput = fileInputs[i]); i++) {if (fileInput.value) {hasFiles = true;}if (!verifyFileType(fileInput)) {// 突出显示出错的文件输入元素if (!ADS.hasClassName(fileInput, 'error')) {ADS.addClassName(fileInput, 'error');}ok = false;}}if (!ok || !hasFiles) {// 如果检查为通过则提示用户解决问题 ADS.preventDefault(event);alert('Please select some valid files');return false;}// 通过发出警告信息来禁用表单元素function warning(event) {ADS.preventDefault(event);alert('There is an upload in progress. Please wait.');}for (var i = 0, input; (input = allInputs[i]); i++) {// input.setAttribute('disabled', 'disabled');ADS.addEvent(input, 'mousedown', warning);}// 创建一个函数以便在上传完成后重启表单// 该函数将在ajax事件侦听器内部被调用function clearWarnings() {// 从表单元素移除警告侦听器for (var i = 0, input; (input = allInputs[i]); i++) {ADS.removeEvent(input, 'mousedown', warning);}// 以新ID数值更新原ID和表单// 以确保下次上传不影响本次上传uniqueID = Math.floor(Math.random() * 100000000000000);uniqueIDFiled.setAttribute('value', uniqueID);}// 更新进度条updateProgressBar('0%', 'Waiting for upload', 'waiting');// 为模拟脚本设置计数器var counter = 0;// 创建一个新方法以触发一次新的进度请求var progressWatcher = function () {// 使用唯一键来请求进度信息ADS.ajaxRequest(form.action + (form.action.indexOf('?') === -1 ? '?' : '&') + 'key=' + uniqueID + '&sim=' + (++counter), {// 服务器端脚本将返回适当的头部信息// 因此我们可以使用JSON侦听器jsonResponseListener: function (response) {// 检测响应以确认服务器端// 脚本中是否存在错误if (!response) {// 没有有效的响应 updateProgressBar('0%','Invalid response from progress watcher','error');// 请求完成故清除警告提示 clearWarnings();} else if (response.error) {// 服务器端报告了错误updateProgressBar('0%', response.error, 'error');// 请求完成故清除警告提示 clearWarnings();} else if (response.done === 1) {// POST请求已经完成updateProgressBar('100%', 'Upload complete', 'complete');// 请求完成故清除警告提示 clearWarnings();// 为提供更改处理程序的// 用户传递新信息if (modificationHander.constructor === Function) {modificationHander(response);}} else {// 更新进度条并返回结果// 由于结果是null, 所以// 返回会简单地停止执行// 方法中其余的代码 updateProgressBar(Math.round(response.current / response.total * 100) + '&',response.current + 'of'+ response.total + '. Uploading file: '+ response.currentFileName,'uploading');// 再次执行进度监视程序setTimeout(progressWatcher, 1000);}},errorListener: function () {// ajax请求发生了错误// 因此需要让用户知道updateProgressBar('0%', this.status, 'error');// 并清除警告提示clearWarnings();}});};// 开始监视setTimeout(progressWatcher, 1000);});};// 主页index.php:<?php// 循环遍历uploads文件夹// 以便取得已经上传的文件$uploads = new DirectoryIterator('./uploads');$files=array();foreach($uploads as $file) {// 跳过,并。。。if(!$file->isDot() && $file->isFile()) {// 添加到数组,。稍后,该数组// 将在HTML中被连接起来$files[]=sprintf('<li><a href="uploads/%s">%s</a> <em>%skb</em></li>',$file->getFilename(),$file->getFilename(),round($file->getSize()/1024) );}}// 输出页面?><!DOCTYPE html><html lang="en"><head><title>Image Uploader with Progress (php5-APC)</title><!-- Inclue some CSS style sheet to makeeverything look a little nicer --><link rel="stylesheet"href="/../shared/source.css" /><link rel="stylesheet"href="/chapter.css" /><link rel="stylesheet" href="style.css" /><!-- Your ADS library with the common JavaScript objects --><script src="/../ADS.js"></script><!-- Progress bar script --><script src="uploader.js"></script><!-- load script --><script src="load.js"></script></head><body><h1>Image Uploader with Progress (php5-APC)</h1><div id="content"><form action="actions/" enctype="multipart/form-data"method="post" id="uploadForm"><fieldset><legend>Upload a new image</legend><p>Only jpg/gif/png files less than 100kb allowed.</p><div class="fileSelector"><label for="newFile1">File 1</label><input type="file" id="newFile1" name="newFile1"accept="image/jpeg,image/gif,image/png"/></div><div class="fileSelector"><label for="newFile2">File 2</label><input type="file" id="newFile2" name="newFile2"accept="image/jpeg,image/gif,image/png"/></div><div class="fileSelector"><label for="newFile3">File 3</label><input type="file" id="newFile3" name="newFile3"accept="image/jpeg,image/gif,image/png"/></div><input id="submitUpload" name="submitUpload"type="submit" value="Upload Files" /></fieldset></form><div id="browserPane"><h2><span id="fileCount"><?php echo count($files); ?></span>Existing Files in <em>uploads/</em></h2><ul id="fileList"><?php echo join($files,"\n\t\t\t\t"); ?></ul></div></div><div id="where-from">From <a href="" title="AdvancED DOM Scripting">AdvancED DOM Scripting</a>| <a href="/exec/obidos/ASIN/1590598563/jeffreysamb05-20" title="Buy it on Amazon">Paperback</a></div></body></html>// 表单action指向的php文件action/index.php: <?php//check if the request is using the ADS.ajaxRequest() method.if($_SERVER['HTTP_X_ADS_AJAX_REQUEST']) {// Return the progress information as a JSON string// Send some headers to prevent caching of the progress requestheader('Expires: Fri, 13 Dec 1901 20:45:54 GMT') ;header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT') ;header('Cache-Control: no-store, no-cache, must-revalidate') ;header('Cache-Control: post-check=0, pre-check=0', false) ;header('Pragma: no-cache') ;// This will be a JavaScript JSON responseheader('Content-Type:application/json; charset=utf-8' ) ;// Retrieve the status using the getStatus() function below echo json_encode(getStatusAPC($_GET['key']));die();} // Process any files in the PHP $_FILES[] array and return to the// main script if everything went well. Otherwise we'll display a// error page.$allowedExtensions = array('jpg','jpeg','gif','png');$errorMessage = null ;$storedFiles = array();if(count($_FILES) > 0) {try {// Process each fileforeach($_FILES as $key=>$info) {if($_FILES[$key]['name']) {// storeFile() throws exceptions$file = storeFile($key,'../uploads/',$allowedExtensions);} else {$file = null;}// Keep track of stored files incase you need to// remove them.$storedFiles[$key] = $file['basename'];}if($_POST['APC_UPLOAD_PROGRESS'] && function_exists('apc_store')) {// Store the file information so it can be // retrieved in the progress watcher apc_store('upload_finished_'.$_POST['APC_UPLOAD_PROGRESS'],$storedFiles);// Die. This message will display in the iframedie('Upload complete.');}// Everything was successful so redirect back // to the main index pageheader('Location: ../');die();} catch (Exception $e) {// There was an error so remove any files that were uploaded foreach($storedFiles as $file) {if(is_file($file)) unlink('uploads/'.$file);}$storedFiles = array();if($_POST['APC_UPLOAD_PROGRESS'] && function_exists('apc_store')) {// Store the error message so it can be // retrieved in the progress watcher apc_store('upload_error_'.$_POST['APC_UPLOAD_PROGRESS'],$e->getMessage());// Die. This message will display in the iframedie('There was an error');} else {// Get the error message$errorMessage = sprintf('<p>%s failed: %s</p>', $key, $e->getMessage());// Display a simple error page with a // link back to the main index file echo <<<XHTML<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="/1999/xhtml"><head><title>Oops!</title></head><body><h1>Error</h1><p>The system reported an error with thefile(s) you were trying to upload:</p> {$errorMessage}<p><a href="../">Return to the upload page</a></p><div id="where-from">From <a href="" title="AdvancED DOM Scripting">AdvancED DOM Scripting</a> | <a href="/exec/obidos/ASIN/1590598563/jeffreysamb05-20" title="Buy it on Amazon">Paperback</a></div></body></html>XHTML;}} }/*** Store a file uploaded through HTTP on the server** This function will access the global $_FILES array to retrieve the * information:** The original name of the file on the client machine.* $_FILES['userfile']['name']** The mime type of the file, if the browser provided this information.* An example would be 'image/gif'. This mime type is however not checked* on the PHP side and therefore don't take its value for granted.* $_FILES['userfile']['type']** The size, in bytes, of the uploaded file.* $_FILES['userfile']['size']** The temporary filename of the file in which the uploaded file was stored on the server.* $_FILES['userfile']['tmp_name']** The error code associated with this file upload.* This element was added in PHP 4.2.0* $_FILES['userfile']['error']** @param string $key The key in $_FILES that represents the file you wish to * store. This is generally the name attribute from the form.* @param string $where The directory on the server where you wish to store * the file. This can be absolute or relative to the location of execution.* @param array $extensions An array of acceptable extensions. (white list)* @param int $maxBytes The maximum number of bytes* @return array*/function storeFile($key,$where,$extensions,$maxBytes=null) {try {// Check for the fileif(!$_FILES[$key]) {throw new Exception('The specified key does not exist in the $_FILES array');}// Check the uplod location if(!$where) {throw new Exception('Upload location not specified. If the current directory is desired, use "."');} elseif ($where[strlen($where)-1] != DIRECTORY_SEPARATOR) {$where .= DIRECTORY_SEPARATOR;}// Check for permissionsif(!is_writeable($where)) {throw new Exception('This page can not access the specified upload directory.');}// convert the extensions to an array// (if a single extension as a string was supplied)settype($extensions,'array');//check for extensionsif(count($extensions) == 0) {throw new Exception('No valid extensions were specified.');}// Convert ini to bytes and store in maxBytes if required$maxBytes = ($maxBytes ? $maxBytes : preg_replace_callback('/([0-9]+)([gmk])/i','toBytes',ini_get('upload_max_filesize')));// check PHP upload errors switch ($_FILES[$key]['error']) {case UPLOAD_ERR_OK:// everything was fine. Proceedbreak;case UPLOAD_ERR_INI_SIZE:throw new Exception('The uploaded file exceeds the upload_max_filesize directive ('.ini_get('upload_max_filesize').') in php.ini.');break;case UPLOAD_ERR_FORM_SIZE:throw new Exception('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.');break;case UPLOAD_ERR_PARTIAL:throw new Exception('The uploaded file was only partially uploaded.');break;case UPLOAD_ERR_NO_FILE:throw new Exception('No file was uploaded.');break;case UPLOAD_ERR_NO_TMP_DIR:throw new Exception('Missing a temporary folder.');break;case UPLOAD_ERR_CANT_WRITE:throw new Exception('Failed to write file to disk');break;default:throw new Exception('Unknown PHP File Error');}// Check if the files size is greater than the // file size in the argumentsif($_FILES['userfile']['size'] > $maxBytes) {throw new Exception('The uploaded file exceeds the maximum size specified in the application.');}// Sanitize the file name$cleanName = str_replace(' ','-',$_FILES[$key]['name']);$cleanName = preg_replace('/-+/','-',$cleanName);$cleanName = preg_replace('/[^a-z0-9_.\/-]/i','',$cleanName);$fileNameParts = pathinfo($cleanName);// Verify the sanitized name is good$fileNameParts['filename'] = str_replace('.','_',$fileNameParts['filename']);if(!$fileNameParts['filename']) {throw new Exception('The desired file name contains no valid characters.');}// Verify the extension is valid$fileNameParts['extension'] = strtolower($fileNameParts['extension']);if(!in_array($fileNameParts['extension'], $extensions)) {throw new Exception('The file extension is not one of: '.join($extensions,', '));}// Postfix the file with a counter to avoid duplicates$count = 0;$postfix = '';while(file_exists($uploadLocation = $where.$fileNameParts['filename'].$postfix.'.'.$fileNameParts['extension'])) {$postfix = '-'.++$count;}// Move the upload into placeif(!move_uploaded_file($_FILES[$key]['tmp_name'], $uploadLocation)) {throw new Exception('Failed to move uploaded tmp file.');}} catch (Exception $e) {// Catch exceptions for garbage collection and error storage// Remove the temp fileif($_FILES[$key] && is_uploaded_file($_FILES[$key]['tmp_name'])) {@unlink($_FILES[$key]['tmp_name']);}// Throw the exception again for developers to catchthrow $e;}// Return the information about the new file using pathinfo$return = pathinfo($uploadLocation);$return['rawname'] = basename($_FILES[$key]['name']);return $return;}function toBytes($matches) {switch(strtolower($matches[2])) {case "k": return $matches[1] * 1024; break;case "m": return $matches[1] * 1048576; break;case "g": return $matches[1] * 1073741824; break;}}/*** PHP 5.2 has a new set of hooks for checking the progress of a file upload* with APC 3.5** /viewvc.cgi/pecl/apc/INSTALL?revision=3.53&view=markup* * apc.rfc1867* RFC1867 File Upload Progress hook handler is only available* if you compiled APC against PHP 5.2.0 or later. When enabled* any file uploads which includes a field called* APC_UPLOAD_PROGRESS before the file field in an upload form* will cause APC to automatically create an upload_* user cache entry where is the value of the* APC_UPLOAD_PROGRESS form entry.* (Default: 0)* */function getStatusAPC($key) {$response = false;// will return false if not foundif($status = apc_fetch('upload_'.$_GET['key'])) {/*status {"total":2676099,"current":102685,"filename":"test_large.jpg","name":"test_file","done":0}*/$response = array('total' => $status['total'],'current' => $status['current'],'currentFileName' => $status['filename'],'currentFieldName' => $status['name'],'filesProcessed' => null,'error' => null,'done' => $status['done'],'debug'=>null);if($message = apc_fetch('upload_error_'.$_GET['key'])) {$response['error'] = $message;$response['debug'] = 'There was an error';} else if ($status['done']==1 && ($filesProcessed = apc_fetch('upload_finished_'.$_GET['key']))) {//wait until the last file processed matches the one in status$response['debug'] = 'Files were processed ';if(($last = array_pop(array_keys(((array)$filesProcessed)))) == $status['name']) {$response['filesProcessed'] = $filesProcessed;$response['debug'] .= ' - all';} else {// Override the done state because the upload // has finished but the server is still processing// the files$response['done']= 0;$response['debug'] .= " - \"$last\" != \"{$status['name']}\"";}}}return $response; }?>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。