<?php
namespace imcat;
/**
* UEditor编辑器通用上传类
*/
class comUpload
{
private $fileField; //文件域名
private $file; //文件上传对象
private $base64; //文件上传对象
private $config; //配置信息
private $oriName; //原始文件名
private $fileName; //新文件名
private $fullName; //完整文件名,即从当前配置目录开始的URL
private $filePath; //完整文件名,即从当前配置目录开始的URL
private $fileSize; //文件大小
private $fileType; //文件类型
private $stateInfo; //上传状态信息,
public $stateMap = array();
/**
* @param string $fileField 表单名称
* @param array $config 配置项
* @param type upload/remote/base64
*/
function __construct($fileField, $config, $type="upload"){
$this->stateMap = basLang::ucfg('cfglibs.upload');
$this->stateMap['ERROR_TYPE_NOT_ALLOWED'] = $this->stateMap['ERROR_TYPE_NOT_ALLOWED'];
$this->fileField = $fileField;
$this->config = $config;
$this->type = $type;
if ($type == "remote") {
$this->saveRemote();
} else if($type == "base64") {
$this->upBase64();
} else {
$this->upFile();
}
}
/**
* 上传文件的主处理方法
* @return mixed
*/
private function upFile(){
$file = $this->file = $_FILES[$this->fileField];
if (!$file) {
$this->stateInfo = $this->getStateInfo("ERROR_FILE_NOT_FOUND");
return;
}
if ($this->file['error']) {
$this->stateInfo = $this->getStateInfo($file['error']);
return;
} else if (!file_exists($file['tmp_name'])) {
$this->stateInfo = $this->getStateInfo("ERROR_TMP_FILE_NOT_FOUND");
return;
} else if (!is_uploaded_file($file['tmp_name'])) {
$this->stateInfo = $this->getStateInfo("ERROR_TMPFILE");
return;
}
$this->oriName = $file['name'];
$this->fileSize = $file['size'];
$this->fileType = $this->getFileExt();
$this->fullName = $this->getFullName();
$this->fileName = $this->getFileName();
//检查文件大小是否超出限制
if (!$this->checkSize()){
$this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED");
return;
}
//检查是否不允许的文件格式
if (!$this->checkType()) {
$this->stateInfo = $this->getStateInfo("ERROR_TYPE_NOT_ALLOWED");
return;
}
//移动文件
if (!move_uploaded_file($file["tmp_name"], $this->fullName)) {
$this->stateInfo = $this->getStateInfo("ERROR_FILE_MOVE");
}else{
$this->upEnd();
}
}
/**
* 处理base64编码的图片上传
* @return mixed
*/
private function upBase64(){
$base64Data = $_POST[$this->fileField];
$img = base64_decode($base64Data);
$this->fileSize = strlen($img);
$this->oriName = 'base64_'.$this->fileSize.'_'.basKeyid::kidRand('f',4).'.png'; //$this->config['oriName']; //
$this->fileType = $this->getFileExt();
$this->fullName = $this->getFullName();
$this->fileName = $this->getFileName();
//检查文件大小是否超出限制
if (!$this->checkSize()) {
$this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED");
return;
}
//移动文件
if (!(comFiles::put($this->fullName, $img))) { //移动失败
$this->stateInfo = $this->getStateInfo("ERROR_WRITE_CONTENT");
} else { //移动成功
$this->upEnd();
}
}
/**
* 拉取远程图片
* @return mixed
*/
private function saveRemote($imgUrl=''){
if(empty($imgUrl)){
$imgUrl = htmlspecialchars($this->fileField);
$imgUrl = str_replace("&", "&", $imgUrl);
}
//http开头验证
if (strpos($imgUrl, "http") !== 0) {
$this->stateInfo = $this->getStateInfo("ERROR_HTTP_LINK");
return;
}
//获取请求头并检测死链
$heads = get_headers($imgUrl);
if (!(stristr($heads[0], "200") && stristr($heads[0], "OK"))) {
$this->stateInfo = $this->getStateInfo("ERROR_DEAD_LINK");
return;
}
// Content-Type验证
if (@stristr($heads['Content-Type'], "image")) {
$this->stateInfo = $this->getStateInfo("ERROR_HTTP_CONTENTTYPE");
return;
}//*/
//打开输出缓冲区并获取远程图片
ob_start();
$context = stream_context_create(
array('http' => array(
'follow_location' => false // don't follow redirects
))
);
readfile($imgUrl, false, $context);
$img = ob_get_contents();
ob_end_clean();
$pinfo = parse_url($imgUrl); // 'http://xxx.cn/dir/file.jpg?x-oss-process=image/resize,m_fill,h_170,w_230;
$this->oriName = isset($pinfo['path']) ? basename($pinfo['path']) : basename($imgUrl);
$this->fileSize = strlen($img);
$this->fileType = $this->getFileExt();
$this->fullName = $this->getFullName();
$this->fileName = $this->getFileName();
//检查文件大小是否超出限制
if (!$this->checkSize()) {
$this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED");
return;
}
//移动文件
if (!(comFiles::put($this->fullName, $img))) { //移动失败
$this->stateInfo = $this->getStateInfo("ERROR_WRITE_CONTENT");
} else { //移动成功
$this->upEnd();
}
}
// 上传End
private function upEnd(){
$this->stateInfo = $this->stateMap[0];
if(in_array($this->fileType,array('.jpg','.jpeg'))){
comImage::compress($this->fullName);
//$res[] = self::compcut($full, $max);
}
}
// 上传错误检查
private function getStateInfo($errCode){
$msg = isset($this->stateMap[$errCode]) ? $this->stateMap[$errCode] : $this->stateMap["ERROR_UNKNOWN"];
$msg = "$errCode:$msg";
return $msg;
}
// 获取文件扩展名
private function getFileExt($flag='0'){
if($flag){ // file.php+ 1.jpg
$ext = strtolower(strchr($this->oriName, '.'));
}else{
$ext = strtolower(strrchr($this->oriName, '.'));
}
if(empty($ext)){ // && $this->type=='remote'
$ext = '.jpg';
} //处理类似图片:http://mmbiz.qpic.cn/mmbiz/kCd...gtw/0
return $ext;
}
// 重命名文件
private function getFullName(){
$_parts = req('_parts');
$_dir = req('_dir');
$ndir = in_array($_parts,array('files')) && usrPerm::issup();
if($ndir){
$folder = DIR_STATIC.'/'.$_dir;
}else{
$folder = comStore::getTmpDir();
} //dump($folder);
return $folder . '/' . $this->getFileName();
}
// 获取文件名
private function getFileName(){
$ext = $this->getFileExt();
$upren = basReq::val('upren','auto');
if($upren=='auto'){ // || in_array($this->type,array('remote','base64'))
$name = basKeyid::kidTemp().$ext;
}else{
if(in_array($this->type,array('remote','base64'))){
$org = $this->oriName;
}else {
$org = str_replace(array($ext),array(''),$this->file["name"]);
}
$org = basStr::filKey($org,'()-.@_~[]'); //-._@()[]
$org = str_replace(array('‘','’','“','”'),array("[",']','[',']'),$org);
$name ="{$org}~".basKeyid::kidRand('f',4).$ext;
}
return $this->fileName = strtolower($name);
}
// 文件类型检测
private function checkType(){
$exf = $this->getFileExt(1);
$ext = $this->getFileExt();
$f1 = preg_match("/[^A-Za-z0-9_\.\-\@]/", $exf); // file.php+ 1.jpg
$f2 = preg_match("/\.(asp|aspx|jsp|php|exe|sh|bat|com)$/", $ext); // |asa|cdx|cer|php2|php3|php4
if($f1 || $f2){
$this->fileType = $exf;
$this->stateInfo = "Error `$ext`!";
return false; //"Error `$ext`!";
}
$flag = $this->config["allowFiles"]==='(supper)' ? true : in_array($ext, $this->config["allowFiles"]);
return $flag;
}
// 文件大小检测
private function checkSize(){
$flag = $this->config["maxSize"]==='(supper)' ? true : $this->fileSize <= ($this->config["maxSize"]*1024 );
return $flag;
}
/**
* 获取当前上传成功文件的各项信息
* @return array
*/
function getFileInfo(){
return array(
"state" => $this->stateInfo,
"url" => comStore::fixTmpDir($this->fullName),
"title" => $this->fileName,
"original" => $this->oriName,
"type" => $this->fileType,
"size" => $this->fileSize
);
}
}