正式接触phpcms模块开发后.开发了几个功能模块.其中遇到了需要批量上传图片的问题.于是开始挖掘phpcms里面的swfupload的用法.
在phpcms里面自带的内容类型里面能够直接指定图片组.不过这样的图片组功能并不是我想用的.我需要上传一整个静态的html文件.需要
能够找到一个方法上传整个文件夹.并且能够保留原来的文件名称.
目的总结如下:
1,不改变系统的文件和目录结构.
2,实现多附件上传功能.
3,能够得到上传后的文件夹名称.
在phpcms中自带了附件上传的功能.我想去用swfupload功能,而这个功能被phpcms的附件上传功能集成进去了.那我要做的就是抽出来并加以修改.
第一步,我来研究研究这个是怎么调用的.
首先,打开firefox浏览器的firebug 打开网络面板.找到phpcm中swfupload呗调出的那个按钮.看看系统是请求的什么连接.
我们去找到这个模块中的这个控制器里面的这个方法.
在phpcms/modoules/attachemet/attachemts.php里面
打开看看,代码如下
然后从$_GET里面得到swfupload的参数args,然后去验证了密匙,密匙通过了去解析args.得到网站的id,得到网站的设置,得到允许上传附件的大小.从cookie里面得到未使用的附件列表.
设置模板里面的各种显示.最后也是最关键的.它使用了swfupload模板.也就是说我要找到这个模板.看看swfupload是怎么引过来的.
模板在这里:phpcms/modules/attachment/templates/swfupload.tpl.php
打开模板文件.模板文件上面引入了一堆文件:
之后是swfupload的样式文件和必要的JS.这里调用了一个系统函数initupload,这个函数到底是干嘛的.
千万别小觑这行.整个swfupload的配置都在这里了.
我们去找找看这个函数.
在phpcms/modules/attachment/functions/golable.func.php里面找到了它的踪迹.代码如下,这个函数的主要作用就是配置swfupload这个插件.
button_image_url: "",
button_width: 75,
button_height: 28,
button_placeholder_id: "buttonPlaceHolder",
button_text_style: "",
button_text_top_padding: 3,
button_text_left_padding: 12,
button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT,
button_cursor: SWFUpload.CURSOR.HAND,
file_dialog_start_handler : fileDialogStart,
file_queued_handler : fileQueued,
file_queue_error_handler:fileQueueError,
file_dialog_complete_handler:fileDialogComplete,
upload_progress_handler:uploadProgress,
upload_error_handler:uploadError,
upload_success_handler:uploadSuccess,
upload_complete_handler:uploadComplete
});
})';
return $init;
}
这个模板使用了一个js来控制
那个id是tab_swf_1
这个是一个div 代码如下.
之后一步我们要在点选完文件之后触发swf的上传方法
会在代码中找到如下代码.这里面调用了swfu.startUpload()方法.这个方法定义的地方在swfupload.js里面.我们无需理会.
怎么在我的程序里面调用这个东东呢
首先一点 我们需要在这个控件出现的模板里面引入这些必要的文件
然后在我们的模板里面想要放置swfupload的地方写上这样的标签
这个地方也就是我之前没有关注的if里面的东西.
拿出来看看
首先它载入了系统的attachment类.并且用到了里面的方法.
程序对上传成功做了echo操作.返回的东西是 返回了编号,上传后的地址,拓展名,文件名.
这些东西是给谁用的啊 我们还得回去看配置文件.
配置文件里面有一段是上传过程中各个事件将触发的方法. 有开始上传的.有上传成功的,有上传失败的.等等.
我们可以看见有一个方法是file_dialog_complete_handler:fileDialogComplete,
其实这些已经升级到swfupload的范畴了.有兴趣可以去研究研究
然后我们在phpcms/static/swfupload/handler.js里面找到这个方法.
看见上传成功后echo出来的数据被解析了.
解析的方法如下
关键的地方来了.我们在swfupload方法里面不是有个attachment的系统类的实例么
真正上传附件是在这里实现的.我们调用了attachment里面的upload方法来实现了文件的上传.
这个attachment文件里面的upload方法在系统类里面 也就是phpcms/libs/classes/attachment.class.php里面
在这个类里面我们可以找到upload方法里面有这样一行
到这里我们就理清思路了.
系统是这么运行的
首先在模板里面引用swfupload(配置文件是用函数生成的)->上传文件->attachment模块里的swfupload方法处理(使用系统的attachment类里面的upload方法循环上传附件.并返回结果给swfupload方法)->处理结果通过swfupload的方法(fileDialogComplete)返回给页面.
在上面我们已经实现了在模板里面引入swfupload.但是我们使用的配置文件和上传附件的方法等都是系统原来自带的.并不能实现我想要的目录结构和文件命名方法.怎么办..
改.
怎么改,首先们要把配置文件改掉. 在自己的模块里面的functions文件夹里面建立自己的函数.我们用自己的函数名称 文件命名为global.func.php这样系统会通过auto_load把我们的函数加载
进去我们把系统中attachment模块functions文件夹下面的global.func.php里面的initupload函数全盘拷贝进来.只修改其中的一行
然后我们去改系统的attachment类 我们在自己的模块下的classes文件夹下面建立一个myattachment.class.php
写一个我们自己的类.去集成系统的attachment类.(记得吧里面的私有方法copy过来.)我们需要修改几行.首先一点是吧upload方法里面的上传目录改掉.然后是改掉文件名的命名方法.
$this->field = $field;
$this->savepath = $this->upload_root.$this->upload_dir.date('Ymd');//这里我们需要修改下.也可以不修改.在我们实例化这个类的时候再来指定目录.
$this->alowexts = $alowexts;
$this->maxsize = $maxsize;
$this->overwrite = $overwrite;
$uploadfiles = array();
$description = isset($GLOBALS[$field.'_description']) ? $GLOBALS[$field.'_description'] : array();
if(is_array($_FILES[$field]['error'])) {
$this->uploads = count($_FILES[$field]['error']);
foreach($_FILES[$field]['error'] as $key => $error) {
if($error === UPLOAD_ERR_NO_FILE) continue;
if($error !== UPLOAD_ERR_OK) {
$this->error = $error;
return false;
}
$uploadfiles[$key] = array('tmp_name' => $_FILES[$field]['tmp_name'][$key], 'name' => $_FILES[$field]['name'][$key], 'type' => $_FILES[$field]['type'][$key], 'size' => $_FILES[$field]['size'][$key], 'error' => $_FILES[$field]['error'][$key], 'description'=>$description[$key],'fn'=>$fn);
}
} else {
$this->uploads = 1;
if(!$description) $description = '';
$uploadfiles[0] = array('tmp_name' => $_FILES[$field]['tmp_name'], 'name' => $_FILES[$field]['name'], 'type' => $_FILES[$field]['type'], 'size' => $_FILES[$field]['size'], 'error' => $_FILES[$field]['error'], 'description'=>$description,'fn'=>$fn);
}
if(!dir_create($this->savepath)) {
$this->error = '8';
return false;
}
if(!is_dir($this->savepath)) {
$this->error = '8';
return false;
}
@chmod($this->savepath, 0777);
if(!is_writeable($this->savepath)) {
$this->error = '9';
return false;
}
if(!$this->is_allow_upload()) {
$this->error = '13';
return false;
}
$aids = array();
foreach($uploadfiles as $k=>$file) {
$fileext = fileext($file['name']);
if($file['error'] != 0) {
$this->error = $file['error'];
return false;
}
if(!preg_match("/^(".$this->alowexts.")$/", $fileext)) {
$this->error = '10';
return false;
}
if($this->maxsize && $file['size'] > $this->maxsize) {
$this->error = '11';
return false;
}
if(!$this->isuploadedfile($file['tmp_name'])) {
$this->error = '12';
return false;
}
//$temp_filename = $this->getname($fileext);//名称在这里.我们需要修改下
$temp_filename = $file['tmp_name'].$fileext; //修改成原来的系统文件名称.
$savefile = $this->savepath.$temp_filename; $savefile = preg_replace("/(php|phtml|php3|php4|jsp|exe|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(\.|$)/i", "_\\1\\2", $savefile); $filepath = preg_replace(new_addslashes("|^".$this->upload_root."|"), "", $savefile); if(!$this->overwrite && file_exists($savefile)) continue; $upload_func = $this->upload_func; if(@$upload_func($file['tmp_name'], $savefile)) { $this->uploadeds++; @chmod($savefile, 0644); @unlink($file['tmp_name']); $file['name'] = iconv("utf-8",CHARSET,$file['name']); $uploadedfile = array('filename'=>$file['name'], 'filepath'=>$filepath, 'filesize'=>$file['size'], 'fileext'=>$fileext, 'fn'=>$file['fn']); $thumb_enable = is_array($thumb_setting) && ($thumb_setting[0] > 0 || $thumb_setting[1] > 0 ) ? 1 : 0; $image = new image($thumb_enable,$this->siteid); if($thumb_enable) { $image->thumb($savefile,'',$thumb_setting[0],$thumb_setting[1]); } if($watermark_enable) { $image->watermark($savefile, $savefile); } $aids[] = $this->add($uploadedfile); } } return $aids; }
在我们自己的控制器里面.我们这个时候就需要加载自己写的类了.
至此.我便完成了我的目的.在不改变系统文件目录的基础上.完成我自己想要的文件上传功能.