UEditor修改之移植SAE
开发一个博客显然离不开一个给力的编辑器,虽然我手痒写了个博客,但是写一个编辑器还是饶了我吧。鉴于百度的UEditor功能强大,可定制,文档 全,所以就决定是UEditor了。但我最终是要把博客架在新浪的SAE上,而新浪把本地文件的IO操作禁止了,使得UEdiotr的附件、图片上传和在 线涂鸦功能都不可用了。好在新浪提供了Storage来支持文件上传,下面我们就利用SAE的Storage对UEditor进行简单的hack。
文件上传修改
首先我们在Storage中创建一个名为"upload"的domain。
我用的UEditor版本是最新的1.2.3.0 PHP版本,在这个版本中,官方提供的PHP上传功能都统一通过调用 ueditor/php/Uploader.class.php 里的Uploader来实现,这样就更好改了。
在构造函数中我们看到upFile这个函数被调用来实现上传。首先,我们解决普通文件的上传,注意到upFile里面的这部分代码:
$this->fullName = $this->getFolder() . '/' . $this->getName(); if ( $this->stateInfo == $this->stateMap[ 0 ] ) { if (!move_uploaded_file($file[ "tmp_name" ],$this->fullName)) { $this->stateInfo = $this->getStateInfo( "MOVE" ); } }
嗯,显然move_upload_file是不能用了,SAE提供了SaeStorage这个类来执行用户文件的存储管理,说明文档戳这里。
把代码改成下面这个样子:
$this->fullName = $this->getFolder() . '/' . $this->getName(); if ( $this->stateInfo == $this->stateMap[ 0 ] ) { if(!defined('SAE_TMP_PATH')){ if ( !move_uploaded_file( $file[ "tmp_name" ] , $this->fullName ) ) { $this->stateInfo = $this->getStateInfo( "MOVE" ); } } else{ $st=new SaeStorage(); $url=$st->upload('upload',$this->fullName, $file[ "tmp_name" ]); if(!$url){ $this->stateInfo = $this->getStateInfo( "MOVE" ); } else{ $this->fullName=$url; } } }
SAE_TMP_PATH是SAE平台上自动定义的常量,我们用它来判定是否是在SAE上(因为还要兼容其他开发环境),如果在SAE上,生成一个 SaeStorage对象,调用upload这个API,第一个参数是在SAE的Storage里创建的Domain,第二个参数是保存的文件名(可以包 含目录,如果目录不存在,Storage会自动创建),第三个参数则是文件的临时名。当图片上传成功后会返回图片的URL,我们直接 令$this->fullName=$url;这样程序就能返回图片的完整地址给UEditor了。但是好像还有点问题。。。
上面代码的第一行调用了getFolder,代码如下:
private function getFolder() { $pathStr = $this->config[ "savePath" ]; if ( strrchr( $pathStr , "/" ) != "/" ) { $pathStr .= "/"; } $pathStr .= date( "Ymd" ); if ( !file_exists( $pathStr ) ) { if ( !mkdir( $pathStr , 0777 , true ) ) { return false; } } return $pathStr; }
似乎mkdir在SAE上不能用,反正Storage会自动帮我们创建目录,所以把这部分搞掉:
private function getFolder() { $pathStr = $this->config[ "savePath" ]; if ( strrchr( $pathStr , "/" ) != "/" ) { $pathStr .= "/"; } $pathStr .= date( "Ymd" ); if(!defined('SAE_TMP_PATH')) { if ( !file_exists( $pathStr ) ) { if ( !mkdir( $pathStr , 0777 , true ) ) { return false; } } } return $pathStr; }
现在我们传个文档试试,文档成功地传上去了,在Storage里面也能看到上传的文件,但是在编辑器里面无法下载却裂了。看看链接的地址,原来 UEditor给我们的地址自动加上了修正地址。在editor_config.js中把所有的图片修正地址都改成""(本地测试的时候记得把URL改成 绝对路径)清除缓存刷新,重试,成功。
文件上传的修改完成。
在线涂鸦修改
由于在线涂鸦也需要保存图片到本地,所以这部分也要改一下。在线涂鸦的处理页面是scrawlUp.php,里面同样调用了调用Uploader来处理 文件的上传,不同的是,涂鸦上传采用了base64编码模式,Uploader调用base64ToImage来完成图片的保存。打开 Uploader.class.php,定位到下面的代码:
/** * 处理base64编码的图片上传 * @param $base64Data * @return mixed */ private function base64ToImage( $base64Data ) { $img = base64_decode( $base64Data ); $this->fileName = time() . rand( 1 , 10000 ) . ".png"; $this->fullName = $this->getFolder() . '/' . $this->fileName; if ( !file_put_contents( $this->fullName , $img ) ) { $this->stateInfo = $this->getStateInfo( "IO" ); return; } $this->oriName = ""; $this->fileSize = strlen( $img ); $this->fileType = ".png"; }
file_put_content是不能用了,Storage提供了write这个API,改成下面的代码:
private function base64ToImage( $base64Data ) { $img = base64_decode( $base64Data ); $this->fileName = "img".time() . rand( 1 , 10000 ) . ".png"; $this->fullName = $this->getFolder() . '/' . $this->fileName; if(!defined('SAE_TMP_PATH')){ if ( !file_put_contents( $this->fullName , $img ) ) { $this->stateInfo = $this->getStateInfo( "IO" ); return; } } else{ $st=new SaeStorage(SAE_ACCESSKEY,SAE_SECRETKEY); $url=$st->write('upload',$this->fullName,$img); if(!$url){ $this->stateInfo = $this->getStateInfo( "IO" ); return; } else{ $this->fullName=$url; } } $this->oriName = ""; $this->fileSize = strlen( $img ); $this->fileType = ".png"; }
在线涂鸦部分的代码修改完成。
图片管理
由于本地图片上传和附件上传方式一样,所以修改完附件上传代码,图片上传也能用了。但是图片的管理部分还是用不了,下面我们就对图片管理部分代码进行修改。
打开imageManager.php这个文件,注意到下面这段代码:
if ( $action == "get" ) { $files = getfiles( $path ); if ( !$files ) return; rsort($files,SORT_STRING); $str = ""; foreach ( $files as $file ) { $str .= $file . "ue_separate_ue"; } echo $str; }
程序通过调用递归函数getfiles来完成图片文件的查找,但是我们的文件都存储在Storage中,所以这部分getfiles对我们来说无用。Storage提供一个很方便的函数getList.
getList(string $domain, [string $prefix = NULL], [int $limit = 10], [int $offset = 0])
第一个参数是Storage的domain,第二个是路径前缀可以用来指定目录或者筛选文件,默认为NULL,第三个是返回条数,第四个是偏移量。将上面的代码改成:
$path = 'upload/'; //最好使用缩略图地址,否则当网速慢时可能会造成严重的延时 $action = htmlspecialchars( $_POST[ "action" ] ); if ( $action == "get" ) { if(!defined('SAE_TMP_PATH')) { $files = getfiles( $path ); if ( !$files ) return; rsort($files,SORT_STRING); $str = ""; foreach ( $files as $file ) { $str .= $file . "ue_separate_ue"; } echo $str; } else { $st=new SaeStorage(); $num=0; while($ret = $st->getList("upload", NULL, 100, $num )){ foreach($ret as $file) { if ( preg_match( "/\.(gif|jpeg|jpg|png|bmp)$/i" , $file ) ) echo $st->getUrl('upload',$file). "ue_separate_ue"; $num++; } } } }
至此,图片管理部分修改完成。
此外还有远程图片抓取getRemoteImage.php,具体修改方法参照在线涂鸦的修改,UEditor到SAE的移植基本完工。