phpcms模块开发之swfupload的使用介绍 |
正式接触phpcms模块开发后.开发了几个功能模块.其中遇到了需要批量上传图片的问题.于是开始挖掘phpcms里面的swfupload的用法. 在phpcms里面自带的内容类型里面能够直接指定图片组.不过这样的图片组功能并不是我想用的.我需要上传一整个静态的html文件.需要 能够找到一个方法上传整个文件夹.并且能够保留原来的文件名称. 目的总结如下: 1,不改变系统的文件和目录结构. 2,实现多附件上传功能. 3,能够得到上传后的文件夹名称. 在phpcms中自带了附件上传的功能.我想去用swfupload功能,而这个功能被phpcms的附件上传功能集成进去了.那我要做的就是抽出来并加以修改. 第一步,我来研究研究这个是怎么调用的. 首先,打开firefox浏览器的firebug 打开网络面板.找到phpcm中swfupload呗调出的那个按钮.看看系统是请求的什么连接. 复制代码 代码如下: ?m=attachment&c=attachments&a=swfupload&args=10,,1&module=&catid=&authkey=b756a93dea2e627293e88fa9d62af709&pc_hash=iXFbo1 我们捕捉到一串这样的请求.调用了attachment模块的attachements控制器里面的swfupload方法. 我们去找到这个模块中的这个控制器里面的这个方法. 在phpcms/modoules/attachemet/attachemts.php里面 打开看看,代码如下 复制代码 代码如下: public function swfupload(){ $grouplist = getcache(grouplist,member); if(isset($_POST[dosubmit])){ //if里面的内容我们暂时不看.因为这是上传之后的处理.我们要先找到是如何引入swfupload的. } else { if($this->isadmin==0 && !$grouplist[$this->groupid][allowattachment]) showmessage(L(att_no_permission)); $args = $_GET[args];//得到参数 $authkey = $_GET[authkey];//得到密匙 if(upload_key($args) != $authkey) showmessage(L(attachment_parameter_error));//验证密匙 extract(getswfinit($_GET[args]));//拆分参数 $siteid = $this->get_siteid();//得到网站id $site_setting = get_site_setting($siteid);//得到网站设置 $file_size_limit = sizecount($site_setting[upload_maxsize]*1024);//允许上传大小 $att_not_used = param::get_cookie(att_json);//得到未处理的文件列表 if(empty($att_not_used) || !isset($att_not_used)) $tab_status = class="on";//如果有未处理的设置标签样式为on if(!empty($att_not_used)) $div_status = hidden;//否则隐藏标签 $att = $this->att_not_used();//获取临时未处理文件列表 include $this->admin_tpl(swfupload);//这个地方才是关键.加载了这个模板. } } 前面的我们就先不管了 ,那是处理上传的东西.我从else开始看.首先验证了是否允许附件上传 然后从$_GET里面得到swfupload的参数args,然后去验证了密匙,密匙通过了去解析args.得到网站的id,得到网站的设置,得到允许上传附件的大小.从cookie里面得到未使用的附件列表. 设置模板里面的各种显示.最后也是最关键的.它使用了swfupload模板.也就是说我要找到这个模板.看看swfupload是怎么引过来的. 模板在这里:phpcms/modules/attachment/templates/swfupload.tpl.php 打开模板文件.模板文件上面引入了一堆文件: 复制代码 代码如下: <?php $show_header = $show_validator = $show_scroll = 1; include $this->admin_tpl(header, attachment);?> <link href="<?php echo JS_PATH?>swfupload/swfupload.css" rel="stylesheet" type="text/css" /> <script language="JavaScript" type="text/javascript" src="<?php echo JS_PATH?>swfupload/swfupload.js"></script> <script language="JavaScript" type="text/javascript" src="<?php echo JS_PATH?>swfupload/fileprogress.js"></script> <script language="JavaScript" type="text/javascript" src="<?php echo JS_PATH?>swfupload/handlers2.js"></script> <script type="text/javascript"> <?php echo initupload($_GET[module],$_GET[catid],$args,$this->userid,$this->groupid,$this->isadmin)?> </script> 首先是引入了头文件.我大概看里一下.里面有jquery什么的.是必要文件.所以一会我们要用的时候也要引入这个头. 之后是swfupload的样式文件和必要的JS.这里调用了一个系统函数initupload,这个函数到底是干嘛的. 千万别小觑这行.整个swfupload的配置都在这里了. 我们去找找看这个函数. 在phpcms/modules/attachment/functions/golable.func.php里面找到了它的踪迹.代码如下,这个函数的主要作用就是配置swfupload这个插件. 复制代码 代码如下: /* flash上传初始化 * 初始化swfupload上传中需要的参数 * @param $module 模块名称 * @param $catid 栏目id * @param $args 传递参数 * @param $userid 用户id * @param $groupid 用户组id * @param $isadmin 是否为管理员模式 */ function initupload($module, $catid,$args, $userid, $groupid = 8, $isadmin = 0){ $grouplist = getcache(grouplist,member); if($isadmin==0 && !$grouplist[$groupid][allowattachment]) return false; extract(getswfinit($args)); $siteid = param::get_cookie(siteid); $site_setting = get_site_setting($siteid); $file_size_limit = $site_setting[upload_maxsize]; $sess_id = SYS_TIME; $swf_auth_key = md5(pc_base::load_config(system,auth_key).$sess_id); $init = var swfu = \\; $(document).ready(function(){ swfu = new SWFUpload({ flash_url:".JS_PATH.swfupload/swfupload.swf?"+Math.random(), upload_url:".APP_PATH.index.php?m=attachment&c=attachments&a=swfupload&dosubmit=1", file_post_name : "Filedata", post_params:{"SWFUPLOADSESSID":".$sess_id.","module":".$module.","catid":".$_GET[catid].","userid":".$userid.","siteid":".$siteid.","dosubmit":"1","thumb_width":".$thumb_width.","thumb_height":".$thumb_height.","watermark_enable":".$watermark_enable.","filetype_post":".$file_types_post.","swf_auth_key":".$swf_auth_key.","isadmin":".$isadmin.","groupid":".$groupid."}, file_size_limit:".$file_size_limit.", file_types:".$file_types.", file_types_description:"All Files", file_upload_limit:".$file_upload_limit.", custom_settings : {progressTarget : "fsUploadProgress",cancelButtonId : "btnCancel"}, button_image_url: "", file_dialog_start_handler : fileDialogStart, 回到正题.我们来看模板swfupload.tpl.php 这个模板使用了一个js来控制<li>以页签的形式显示.我们可以用firebug去找到带有我们要找到的swfupload按钮的那个页签的id 那个id是tab_swf_1 这个是一个div 代码如下. 复制代码 代码如下: <div id="div_swf_1" class="content pad-10 <?php echo $div_status?>"> <div> <div class="addnew" id="addnew"> <span id="buttonPlaceHolder"></span> </div> <input type="button" id="btupload" value="<?php echo L(start_upload)?>" onClick="swfu.startUpload();" /> <div id="nameTip" class="onShow"><?php echo L(upload_up_to)?><font color="red"> <?php echo $file_upload_limit?></font> <?php echo L(attachments)?>,<?php echo L(largest)?> <font color="red"><?php echo $file_size_limit?></font></div> <div class="bk3"></div> <div class="lh24"><?php echo L(supported)?> <font style="font-family: Arial, Helvetica, sans-serif"><?php echo str_replace(array(*.,;),array(,、),$file_types)?></font> <?php echo L(formats)?></div><input type="checkbox" id="watermark_enable" value="1" <?php if(isset($watermark_enable) &&$watermark_enable == 1) echo checked?> onclick="change_params()"> <?php echo L(watermark_enable)?> 在这里我们看到有一个span id是buttonPlaceHolder 而在配置文件中有这么一行button_placeholder_id: "buttonPlaceHolder",很明显.当页面被加载的时候 id为buttonPlaceHolder的元素会被JS替换成swfupload的上传控件. 之后一步我们要在点选完文件之后触发swf的上传方法 会在代码中找到如下代码.这里面调用了swfu.startUpload()方法.这个方法定义的地方在swfupload.js里面.我们无需理会. 复制代码 代码如下: <input type="button" id="btupload" value="<?php echo L(start_upload)?>" onClick="swfu.startUpload();" /> 至此.我们已经找到了swfupload的上传控件使用方法 怎么在我的程序里面调用这个东东呢 首先一点 我们需要在这个控件出现的模板里面引入这些必要的文件 复制代码 代码如下: <link href="<?php echo JS_PATH?>swfupload/swfupload.css" rel="stylesheet" type="text/css" /> <script language="JavaScript" type="text/javascript" src="<?php echo JS_PATH?>swfupload/swfupload.js"></script> <script language="JavaScript" type="text/javascript" src="<?php echo JS_PATH?>swfupload/fileprogress.js"></script> <script language="JavaScript" type="text/javascript" src="<?php echo JS_PATH?>swfupload/handlers2.js"></script> <script type="text/javascript"> <?php echo initupload($_GET[module],$_GET[catid],$args,$this->userid,$this->groupid,$this->isadmin)?> </script> 代码如上所示. 然后在我们的模板里面想要放置swfupload的地方写上这样的标签 复制代码 代码如下: <span id="buttonPlaceHolder"></span> <input type="button" id="btupload" value="<?php echo L(start_upload)?>" onClick="swfu.startUpload(); 这样我们就已经把swfupload引入到我们需要的地方了.接着就是能够正常执行上传等功能. 但是这样还不能达到我们的需求.而且有一个问题.我们把文件上传到神马地方去了.那我们就来找找我们把文件上传到神马地方去了 在配置文件(用initupload函数输出的)里面有这样一行 复制代码 代码如下: upload_url:".APP_PATH.index.php?m=attachment&c=attachments&a=swfupload&dosubmit=1", 这个很明显就透露出了我们把文件上传到了attachment模块中attachments控制器里面的swfupload方法去处理了 这个地方也就是我之前没有关注的if里面的东西. 拿出来看看 复制代码 代码如下: if( $_POST[swf_auth_key] != md5(pc_base::load_config(system,auth_key).$_POST[SWFUPLOADSESSID]) || ($_POST[isadmin]==0 && !$grouplist[$_POST[groupid]][allowattachment])) exit(); pc_base::load_sys_class(attachment,,0); $attachment = new attachment($_POST[module],$_POST[catid],$_POST[siteid]); $attachment->set_userid($_POST[userid]); $aids = $attachment->upload(Filedata,$_POST[filetype_post],,,array($_POST[thumb_width],$_POST[thumb_height]),$_POST[watermark_enable]); if($aids[0]) { $filename= (strtolower(CHARSET) != utf-8) ? iconv(gbk, utf-8, $attachment->uploadedfiles[0][filename]) : $attachment->uploadedfiles[0][filename]; if($attachment->uploadedfiles[0][isimage]) { echo $aids[0].,.$this->upload_url.$attachment->uploadedfiles[0][filepath].,.$attachment->uploadedfiles[0][isimage].,.$filename; } else { $fileext = $attachment->uploadedfiles[0][fileext]; if($fileext == zip || $fileext == rar) $fileext = rar; elseif($fileext == doc || $fileext == docx) $fileext = doc; elseif($fileext == xls || $fileext == xlsx) $fileext = xls; elseif($fileext == ppt || $fileext == pptx) $fileext = ppt; elseif ($fileext == flv || $fileext == swf || $fileext == rm || $fileext == rmvb) $fileext = flv; else $fileext = do; echo $aids[0].,.$this->upload_url.$attachment->uploadedfiles[0][filepath].,.$fileext.,.$filename; } exit; } else { echo 0,.$attachment->error(); exit; 这个里面有几行是比较重要的. 首先它载入了系统的attachment类.并且用到了里面的方法. 程序对上传成功做了echo操作.返回的东西是 返回了编号,上传后的地址,拓展名,文件名. 这些东西是给谁用的啊 我们还得回去看配置文件. 配置文件里面有一段是上传过程中各个事件将触发的方法. 有开始上传的.有上传成功的,有上传失败的.等等. 我们可以看见有一个方法是file_dialog_complete_handler:fileDialogComplete, 其实这些已经升级到swfupload的范畴了.有兴趣可以去研究研究 然后我们在phpcms/static/swfupload/handler.js里面找到这个方法. 看见上传成功后echo出来的数据被解析了. 解析的方法如下 复制代码 代码如下: function att_show(serverData,file) { var serverData = serverData.replace(/<div.*?<\/div>/g,); var data = serverData.split(,); var id = data[0]; var src = data[1]; var ext = data[2]; var filename = data[3]; if(id == 0) { alert(src) return false; } if(ext == 1) { var img = <a href="javascript:;" onclick="javascript:att_cancel(this,+id+,\upload\)" class="on"><div class="icon"></div><img src="+src+" width="80" imgid="+id+" path="+src+" title="+filename+"/></a>; } else { var img = <a href="javascript:;" onclick="javascript:att_cancel(this,+id+,\upload\)" class="on"><div class="icon"></div><img src="statics/images/ext/+ext+.png" width="80" imgid="+id+" path="+src+" title="+filename+"/></a>; } $.get(index.php?m=attachment&c=attachments&a=swfupload_json&aid=+id+&src=+src+&filename=+filename); $(#fsUploadProgress).append(<li><div id="attachment_+id+" class="img-wrap"></div></li>); $(#attachment_+id).html(img); $(#att-status).append(|+src); $(#att-name).append(|+filename); } 这个方法的目的是在id为fsuuploadprogress的元素里面添加我们上传成功的附件.但是我们还木有找到文件到底去哪里了 关键的地方来了.我们在swfupload方法里面不是有个attachment的系统类的实例么 真正上传附件是在这里实现的.我们调用了attachment里面的upload方法来实现了文件的上传. 这个attachment文件里面的upload方法在系统类里面 也就是phpcms/libs/classes/attachment.class.php里面 在这个类里面我们可以找到upload方法里面有这样一行 复制代码 代码如下: $this->savepath = $this->upload_root.$this->upload_dir.date(Y/md/); 这个自然就是指定了上传到的目录.文件名是通过getname方法来获取的. 到这里我们就理清思路了. 系统是这么运行的 首先在模板里面引用swfupload(配置文件是用函数生成的)->上传文件->attachment模块里的swfupload方法处理(使用系统的attachment类里面的upload方法循环上传附件.并返回结果给swfupload方法)->处理结果通过swfupload的方法(fileDialogComplete)返回给页面. 在上面我们已经实现了在模板里面引入swfupload.但是我们使用的配置文件和上传附件的方法等都是系统原来自带的.并不能实现我想要的目录结构和文件命名方法.怎么办.. 改. 怎么改,首先们要把配置文件改掉. 在自己的模块里面的functions文件夹里面建立自己的函数.我们用自己的函数名称 文件命名为global.func.php这样系统会通过auto_load把我们的函数加载 进去我们把系统中attachment模块functions文件夹下面的global.func.php里面的initupload函数全盘拷贝进来.只修改其中的一行 复制代码 代码如下: upload_url:".APP_PATH.index.php?m=你的模块名称&c=你的控制器名称&a=你的方法名称&dosubmit=1", 这样文件就会提交到我们的控制器下面.并且调用我们自己写的方法 然后我们去改系统的attachment类 我们在自己的模块下的classes文件夹下面建立一个myattachment.class.php 写一个我们自己的类.去集成系统的attachment类.(记得吧里面的私有方法copy过来.)我们需要修改几行.首先一点是吧upload方法里面的上传目录改掉.然后是改掉文件名的命名方法. 复制代码 代码如下: function upload($field, $alowexts = , $maxsize = 0, $overwrite = 0,$thumb_setting = array(), $watermark_enable = 1) { if(!isset($_FILES[$field])) { $this->error = UPLOAD_ERR_OK; return false; } if(empty($alowexts) || $alowexts == ) { $site_setting = $this->_get_site_setting($this->siteid); $alowexts = $site_setting[upload_allowext]; } $fn = $_GET[CKEditorFuncNum] ? $_GET[CKEditorFuncNum] : 1; $this->field = $field; if(!dir_create($this->savepath)) { if(!is_writeable($this->savepath)) { 注:这里我们可以再系统的attachment模块下建立MY_attachment.php 但是这样会影响系统的附件上传功能. 在我们自己的控制器里面.我们这个时候就需要加载自己写的类了. 复制代码 代码如下: pc_base::load_app_class(你的模块名,,0); 其余的操作可以参照系统的attachment模块下的attachments控制器里面的swfupload方法来修改. 至此.我便完成了我的目的.在不改变系统文件目录的基础上.完成我自己想要的文件上传功能. |