博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PHP_APC+Ajax实现的监视进度条的文件上传
阅读量:4517 次
发布时间:2019-06-08

本文共 21136 字,大约阅读时间需要 70 分钟。

// load.js:ADS.addEvent(window, 'load', function (event) {    var fileList = ADS.$('fileList');    // 按照需要修改uoloadForm    addProgressBar('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 = '';    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: 
isDot() && $file->isFile()) { // 添加到数组,。稍后,该数组 // 将在HTML中被连接起来 $files[]=sprintf( '
  • %s %skb
  • ', $file->getFilename(), $file->getFilename(), round($file->getSize()/1024) ); }}// 输出页面?> Image Uploader with Progress (php5-APC)

    Image Uploader with Progress (php5-APC)

    Upload a new image

    Only jpg/gif/png files less than 100kb allowed.

    Existing Files in uploads/

    // 表单action指向的php文件action/index.php:
    0) { try { // Process each file foreach($_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 iframe die('Upload complete.'); } // Everything was successful so redirect back // to the main index page header('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 iframe die('There was an error'); } else { // Get the error message $errorMessage = sprintf( '

    %s failed: %s

    ', $key, $e->getMessage() ); // Display a simple error page with a // link back to the main index file echo <<
    Oops!

    Error

    The system reported an error with the file(s) you were trying to upload:

    {$errorMessage}

    Return to the upload page

    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 file if(!$_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 permissions if(!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 extensions if(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. Proceed break; 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 arguments if($_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 place if(!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 file if($_FILES[$key] && is_uploaded_file($_FILES[$key]['tmp_name'])) { @unlink($_FILES[$key]['tmp_name']); } // Throw the exception again for developers to catch throw $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 * * http://viewcvs.php.net/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 found if($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; }?>

     

    转载于:https://www.cnblogs.com/webFrontDev/archive/2013/02/24/2926138.html

    你可能感兴趣的文章
    剑指Offer学习笔记(3)——解决面试题的思路
    查看>>
    .NET Framework基础知识(二)(转载)
    查看>>
    Yii DataProvider
    查看>>
    BestCoder Round #14 B 称号 Harry And Dig Machine 【TSP】
    查看>>
    hdu 1114 Piggy-Bank
    查看>>
    maven集成tomcat插件启动报错
    查看>>
    Boost库编译安装
    查看>>
    Python matplot画散列图
    查看>>
    C#/.NET整数的三种强制类型转换(int)、Convert.ToInt32()、int.Parse()的区别
    查看>>
    算法复习——数位dp(不要62HUD2089)
    查看>>
    PhpSpreadsheet如何读取excel文件
    查看>>
    如何选购一款好的人事档案管理系统
    查看>>
    Spark2.1.0——运行环境准备
    查看>>
    [转载]C#异步调用四大方法详解
    查看>>
    在windows下添加php的Imagick扩展
    查看>>
    python3 爬取百合网的女人们和男人们
    查看>>
    kubernetes源码阅读笔记——Kubelet(之三)
    查看>>
    如何利用jQuery post传递含特殊字符的数据
    查看>>
    中国剩余定理
    查看>>
    Codeforces 543.B Destroying Roads
    查看>>