🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
plupload支持技术: 1:Flash 2:Gears 3:HTML 5 4:Silverlight 5:BrowserPlus 6:HTML 4 plupload主要功能: 1:突破HTTP上传限制,可上传大文件,官方论坛中有讨论上传2G文件的应用。 2:多文件队列上传 3:图片自动生成缩略图 4:上传后自动生成唯一文件名 5:自定制UI   由于plupload 确实是一个功能比较强大的组件所以无法一一介绍所有功能特色,这里主要就网站开发中plupload上传大文件的问题进行思路与代码的解析 。   大文件上传思路:plupload的上传思路是将一个较大的文件分成多个小块进行上传从而达到突破服务器上传限制的目的。这估计也是唯一的方法了,但本人测试过程中根据虚拟主机差异分块上传时对于可能会出现块数太多中断的原因,但这肯定是服务器的配置问题,更换服务器后该问题解决,也就是说大部分服务器均没有问题的。   下载最新版本后按照官方DEMO进行安装。   JS参数配置说明: ~~~ <script type="text/javascript"> $(function() { $("#uploader").pluploadQueue({ runtimes : 'gears,flash,silverlight,browserplus,html5', // 这里是说用什么技术引擎,由于国内浏览器问题这里一般使用flash即可。其他的删除掉。 url : 'upload.php', // 服务端上传路径 max_file_size : '10mb', // 文件上传最大限制。 chunk_size : '1mb', // 上传分块每块的大小,这个值小于服务器最大上传限制的值即可。(文件总大小/chunk_size = 分块数)。 unique_names : true, // 上传的文件名是否唯一 resize : {width : 320, height : 240, quality : 90}, // 是否生成缩略图(仅对图片文件有效)。 filters : [ {title : "Image files", extensions : "jpg,gif,png"}, {title : "Zip files", extensions : "zip"} ], // 这个数组是选择器,就是上传文件时限制的上传文件类型 flash_swf_url : '/plupload/js/plupload.flash.swf', // plupload.flash.swf 的所在路径 silverlight_xap_url : '/plupload/js/plupload.silverlight.xap' // silverlight所在路径 }); // 这一块主要是防止在上传未结束前表带单提交,具体大家可酌情修改编写 $('form').submit(function(e) { var uploader = $('#uploader').pluploadQueue(); // 取得上传队列 if (uploader.files.length > 0) { // 就是说如果上传队列中还有文件 uploader.bind('StateChanged', function() { if (uploader.files.length === (uploader.total.uploaded + uploader.total.failed)) { $('form')[0].submit(); } }); uploader.start(); } else { alert('You must queue at least one file.'); } return false; }); }); </script> ~~~   由于参数过多大家可以到官方网站查看API参数说明。 服务端代码说明:   官方自带了PHP版本的DEMO文件。大家一定要参考这个DEMO进行编写或者直接使用。在此我简单的做一下官方upload.php的注释说明。 ~~~ <?php // HTTP headers for no cache etc 头部没有缓存 header("Expires: Mon, 26 Jul 1997 05:00:00 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"); //上传路径 $targetDir = 'uploads/'; // 脚本执行时间 @set_time_limit(5 * 60); // 延迟 // usleep(5000); // 接收 pluploa的参数 $chunk = isset($_REQUEST["chunk"]) ? $_REQUEST["chunk"] : 0; $chunks = isset($_REQUEST["chunks"]) ? $_REQUEST["chunks"] : 0; $fileName = isset($_REQUEST["name"]) ? $_REQUEST["name"] : ''; // 文件名整理 $fileName = preg_replace('/[^\w\._]+/', '', $fileName); // 这里主要是如果JS参数设置了唯一文件名,则进行唯一文件名的处理,chunks<2 的意思是只有在不分块上传的情况下才会进行唯一文件名。否则将和分块上传的原理冲突,第1块以后的文件流将无法写入正确的文件中。 if ($chunks < 2 && file_exists($targetDir . DIRECTORY_SEPARATOR . $fileName)) { $ext = strrpos($fileName, '.'); $fileName_a = substr($fileName, 0, $ext); $fileName_b = substr($fileName, $ext); $count = 1; while (file_exists($targetDir . DIRECTORY_SEPARATOR . $fileName_a . '_' . $count . $fileName_b)) $count++; $fileName = $fileName_a . '_' . $count . $fileName_b; } /*创建文件目录*/ if (!file_exists($targetDir)) @mkdir($targetDir); if (is_dir($targetDir) && ($dir = opendir($targetDir))) { while (($file = readdir($dir)) !== false) { $filePath = $targetDir . DIRECTORY_SEPARATOR . $file; // Remove temp files if they are older than the max age if (preg_match('/\\.tmp$/', $file) && (filemtime($filePath) < time() - $maxFileAge)) @unlink($filePath); } closedir($dir); } else die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory."}, "id" : "id"}'); */ // 上传写文件步骤,这一部分以下的代码可直接引用 if (isset($_SERVER["HTTP_CONTENT_TYPE"])) $contentType = $_SERVER["HTTP_CONTENT_TYPE"]; if (isset($_SERVER["CONTENT_TYPE"])) $contentType = $_SERVER["CONTENT_TYPE"]; // Handle non multipart uploads older WebKit versions didn't support multipart in HTML5 if (strpos($contentType, "multipart") !== false) { if (isset($_FILES['file']['tmp_name']) && is_uploaded_file($_FILES['file']['tmp_name'])) { // Open temp file $out = fopen($targetDir . DIRECTORY_SEPARATOR . $fileName, $chunk == 0 ? "wb" : "ab"); if ($out) { // Read binary input stream and append it to temp file $in = fopen($_FILES['file']['tmp_name'], "rb"); if ($in) { while ($buff = fread($in, 4096)) fwrite($out, $buff); } else die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}'); fclose($in); fclose($out); @unlink($_FILES['file']['tmp_name']); } else die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}'); } else die('{"jsonrpc" : "2.0", "error" : {"code": 103, "message": "Failed to move uploaded file."}, "id" : "id"}'); } else { // Open temp file $out = fopen($targetDir . DIRECTORY_SEPARATOR . $fileName, $chunk == 0 ? "wb" : "ab"); if ($out) { // Read binary input stream and append it to temp file $in = fopen("php://input", "rb"); if ($in) { while ($buff = fread($in, 4096)) fwrite($out, $buff); } else die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}'); fclose($in); fclose($out); } else die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}'); } // Return JSON-RPC response die('{"jsonrpc" : "2.0", "result" : null, "id" : "id"}'); ?> ~~~ #### **配置文档说明:** Browse_button:触发浏览文件按钮标签的唯一id,,在flash、html5、和silverlight中能找到触发事件的 Container: 展现上传文件列表的容器,[默认是body] chunk_size:当上传文件大于服务器接收端文件大小限制的时候,可以分多次请求发给服务器,如果不需要从设置中移出 drop_element:当浏览器支持拖拽的情况下,能够文件拖放到你想要的容器ID里 file_data_name:设置上传字段的名称。默认情况下被设置为文件。(我试验了没找到该如何使用它,暂且不提) filters:选择文件扩展名的过滤器,每个过滤规则中只有title和ext两项[{title:'', extensions:''}] flash_swf_url:flash文件地址 headers:自定义的插入http请求的键值对 max_file_size:最大上传文件大小(格式100b, 10kb, 10mb, 1gb) multipart:布尔值,如果用mutlipart 代替二进制流的方式,在webkit下无法工作 multipart_params: 跟 multipart关联在一起的键值对 multi_selection: 多选对话框 resize:修改图片属性 resize: {width: 320, height: 240, quality: 90} runtimes:上传插件初始化选用那种方式的优先级顺序,如果第一个初始化失败就走第二个,依次类推 required_features:需要那些特性,才能初始化插件 url:上传服务器地址 unique_names:是否生成唯一的文件名,避免与服务器文件重名 urlstream_upload:布尔值 如果是flash上传应该用URLStream 代替FileReference.upload #### **jquery部件的属性:** dragdrop:是否支持拖拽,默认值true multiple_queues:是否可以多次上传 preinit:插件初始化前回调函数 rename:布尔值,上传之前可以重命名文件,默认false, API文档:方法列表: Uploader(setting):创建实例的构造方法 var uploader = new plupload.Uploader({ runtimes : 'gears,html5,flash', browse_button : 'button_id' }); bind(event, function[, scope]):绑定事件 uploader.bind('Init', function(up) { alert('Supports drag/drop: ' + (!!up.features.dragdrop)); }); destroy():销毁plupload的实例对象 uploader.destroy() getFile(id): 获取上传文件信息 uploader.bind('FilesAdded', function(up, files) { for (var i in files) { up.getFile(files[i].id); } }); 注:file:{   id:文件编号,   loaded: 已经上传多少字节,   name: 文件名,   percent: 上传进度,   size: 文件大小,   status: 有四种状态 QUEUED, UPLOADING, FAILED, DONE.对应数值 } init:初始化plupload实例,添加监听对象 refresh:重新实例化uploader removeFile(id):从file中移除某个文件 splice(start,length):从队列中start开始删除length个文件, 返回被删除的文件列表 start() 开始上传 stop()停止上传 unbind(name, function): 接触事件绑定 unbindAll()解绑所有事件 属性集合: features:uploader中包含那些特性 files:当前队列中的文件列表 id:uploader实例的唯一id runtime:当前运行环境(是html5、flash等等) state:当前上传进度状态 total:当前上传文件的信息集合 事件集合:(up为uploader缩写) BeforeUpload(up, file):文件上传完之前触发的事件 ChunkUploaded(up, file,response)文件被分块上传的事件 Destroy(up):uploader的destroy调用的方法 Error(up, err):上传出错的时候触发 Fileadded(up, files):用户选择文件时触发 FileRemoved(up, files):当文件从上传队列中移除触发 FileUploaded(up, file, res):文件上传成功的时候触发 Init(up):当初始化的时候触发 PostInit(up):init执行完以后要执行的事件触发 QueueChanged(up):当文件队列变化时触发 Refresh(up):当silverlight/flash或是其他运行环境需要移动的时候触发 StateChanged(up)当整个上传队列被改变的时候触发 UploadComplete(up,file)当队列中所有文件被上传完时触发 UploadFile(up,file)当一个文件被上传的时候触发 UploadProgress(up,file):当文件正在被上传中触发 获取上传文件值: 前台上传文件后提交,在控制器中 print_r($_POST),就会得到下面信息 [uploader_0_tmpname] => p17bfctda8kdq19711p7ck4e1jqv1.png [uploader_0_name] => ques_title.png [uploader_0_status] => done [uploader_1_tmpname] => p17bfctda81b5idpc1ek01u8a1tjf2.jpg [uploader_1_name] => title2bg.jpg [uploader_1_status] => done [uploader_count] => 2 上面传了2张图片 [uploader_0_tmpname] 表示第一张图片的临时文件名 ; [uploader_0_name] 表示第一张图片的原文件名 [uploader_0_status] => done 表示文件上传状态,done表示成功 [uploader_1_tmpname] 表示第二张图片的临时文件名 ; [uploader_1_name] 表示第二张图片的原文件名 [uploader_1_status] => done 表示文件上传状态,done表示成功 以此类推...... [uploader_count] 表示上传文件的个数,一般用来获取文件总数 放入数组中: ~~~ $sum= $_POST['uploader_count']; for ($i = 0; $i < $sum; $i++) { $con[] = $_POST["uploader_" . $i . "_tmpname"]; } ~~~ $con 数组就是上传的文件的临时文件名