[ /* 文件上传的根目录 */ //'rootPath' => $_SERVER['DOCUMENT_ROOT'], /* 上传图片配置项 */ "imageActionName" => "uploadimage", /* 执行上传图片的action名称 */ "imageFieldName" => "file", /* 提交的图片表单名称 */ "imageMaxSize" => 20480000, /* 银联文件上传大小限制,单位B */ "imageMaxSize_union" => 2097152, /* 上传大小限制,单位B */ "imageAllowFiles" => [ ".png", ".jpg", ".jpeg", ".gif", ".ico", ".bmp" ], /* 上传图片格式显示 */ "imageCompressEnable" => true, /* 是否压缩图片,默认是true */ "imageCompressBorder" => 800, /* 图片压缩最长边限制 */ "imageInsertAlign" => "none", /* 插入的图片浮动方式 */ "imageUrlPrefix" => "", /* 图片访问路径前缀 */ "imagePathFormat" => "/upload/image/{yyyy}/{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */ /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */ /* {time} 会替换成时间戳 */ /* {yyyy} 会替换成四位年份 */ /* {yy} 会替换成两位年份 */ /* {mm} 会替换成两位月份 */ /* {dd} 会替换成两位日期 */ /* {hh} 会替换成两位小时 */ /* {ii} 会替换成两位分钟 */ /* {ss} 会替换成两位秒 */ /* 非法字符 \ => * ? " < > | */ /* 具请体看线上文档=> fex.baidu.com/ueditor/#use-format_upload_filename */ /* 涂鸦图片上传配置项 */ "scrawlActionName" => "uploadscrawl", /* 执行上传涂鸦的action名称 */ "scrawlFieldName" => "file", /* 提交的图片表单名称 */ "scrawlPathFormat" => "/upload/image/{yyyy}/{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ "scrawlMaxSize" => 2048000, /* 上传大小限制,单位B */ "scrawlUrlPrefix" => "", /* 图片访问路径前缀 */ "scrawlInsertAlign" => "none", /* 截图工具上传 */ "snapscreenActionName" => "uploadimage", /* 执行上传截图的action名称 */ "snapscreenPathFormat" => "/upload/image/{yyyy}/{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ "snapscreenUrlPrefix" => "", /* 图片访问路径前缀 */ "snapscreenInsertAlign" => "none", /* 插入的图片浮动方式 */ /* 抓取远程图片配置 */ "catcherLocalDomain" => [ "127.0.0.1", "localhost", "img.baidu.com" ], "catcherActionName" => "catchimage", /* 执行抓取远程图片的action名称 */ "catcherFieldName" => "source", /* 提交的图片列表表单名称 */ "catcherPathFormat" => "/upload/image/{yyyy}/{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ "catcherUrlPrefix" => "", /* 图片访问路径前缀 */ "catcherMaxSize" => 2048000, /* 上传大小限制,单位B */ "catcherAllowFiles" => [ ".png", ".jpg", ".jpeg", ".gif", ".ico", ".bmp" ], /* 抓取图片格式显示 */ /* 上传视频配置 */ "videoActionName" => "uploadvideo", /* 执行上传视频的action名称 */ "videoFieldName" => "file", /* 提交的视频表单名称 */ "videoPathFormat" => "/upload/video/{yyyy}/{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ "videoUrlPrefix" => "", /* 视频访问路径前缀 */ // "videoMaxSize" => 5120000, "videoMaxSize" => 52428800, /* 上传大小限制,单位B,默认100MB */ "videoAllowFiles" => [ ".flv", // ".swf", // ".mkv", // ".avi", // ".rm", ".rmvb", ".mpeg", ".mpg", // ".ogg", // ".ogv", // ".mov", ".wmv", ".mp4", // ".webm", ".mp3", ".wav", // ".mid" ], /* 上传视频格式显示 */ /* 上传文件配置 */ "fileActionName" => "uploadfile", /* controller里,执行上传视频的action名称 */ "fileFieldName" => "file", /* 提交的文件表单名称 */ "filePathFormat" => "/upload/file/{yyyy}/{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ "fileUrlPrefix" => "", /* 文件访问路径前缀 */ "fileMaxSize" => 51200000, /* 上传大小限制,单位B,默认50MB */ "fileAllowFiles" => [ ".png", ".jpg", ".jpeg", ".gif", ".ico", ".bmp", ".flv", //".swf", //".mkv", ".avi", //".rm", ".rmvb", //".mpeg", //".mpg", ".ogg", //".ogv", //".mov", ".wmv", ".mp4", //".webm", ".mp3", ".wav", //".mid", ".rar", ".zip", //".tar", //".gz", //".7z", //".bz2", //".cab", //".iso", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".ply", ".xml" ], /* 上传文件格式显示 */ /* 列出指定目录下的图片 */ "imageManagerActionName" => "listimage", /* 执行图片管理的action名称 */ "imageManagerListPath" => "/upload/image/", /* 指定要列出图片的目录 */ "imageManagerListSize" => 20, /* 每次列出文件数量 */ "imageManagerUrlPrefix" => "", /* 图片访问路径前缀 */ "imageManagerInsertAlign" => "none", /* 插入的图片浮动方式 */ "imageManagerAllowFiles" => [ ".png", ".jpg", ".jpeg", ".gif", ".ico", ".bmp" ], /* 列出的文件类型 */ /* 列出指定目录下的文件 */ "fileManagerActionName" => "listfile", /* 执行文件管理的action名称 */ "fileManagerListPath" => "/upload/file/", /* 指定要列出文件的目录 */ "fileManagerUrlPrefix" => "", /* 文件访问路径前缀 */ "fileManagerListSize" => 20, /* 每次列出文件数量 */ "fileManagerAllowFiles" => [ ".png", ".jpg", ".jpeg", ".gif", ".ico", ".bmp", ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" ] /* 列出的文件类型 */ ] ]; public function actionIndex() { //设置允许的跨域header header('Access-Control-Allow-Headers: X-Requested-With,X_Requested_With'); $action = Yii::$app->request->get("action"); $action = htmlspecialchars($action); switch ($action) { case 'config': $result = json_encode($this->uploadConfig['uploadFile']); break; /* 上传图片 */ case 'uploadimage': /* 上传涂鸦 */ case 'uploadscrawl': /* 上传视频 */ case 'uploadvideo': /* 上传文件 */ case 'uploadfile': if(isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == "OPTIONS"){ //判断实际发送的请求是否安全 $result = ""; } else { if(Yii::$app->request->isPost && !empty($_FILES)){ //上传 $currentFileInfo = $this->uploadFile($action); $result = json_encode($currentFileInfo); } else { $result = ""; } } break; /* 列出图片 */ case 'listimage': if(isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == "OPTIONS"){ $result = ""; } else { //返回结果 $result = $this->getFileList($action); } break; /* 列出文件 */ case 'listfile': if(isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == "OPTIONS"){ $result = ""; } else { //返回结果 $result = $this->getFileList($action); } break; /* 抓取远程文件 */ case 'catchimage': if(isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == "OPTIONS"){ $result = ""; } else { //返回结果 $result = $this->crawlerImage($action); } break; default: $result = json_encode(array( 'state'=> '请求地址出错' )); break; } /* 输出结果 */ if (isset($_GET["callback"])) { if (preg_match("/^[\w_]+$/", $_GET["callback"])) { echo htmlspecialchars($_GET["callback"]) . '(' . $result . ')'; } else { echo json_encode(array( 'state'=> 'callback参数不合法' )); } } else { echo $result; } } //上传图片 public function actionImage() { if(!\Yii::$app->request->isPost){ $data = [ 'code' => 1, 'msg' => "Invalid Request" ]; return $this->responseHandler($data); } $action = "uploadimage"; $fileInfo = $this->uploadFile($action); if($fileInfo["state"] == "SUCCESS"){ $data = [ 'code' => 0, 'msg' => 'success', 'data' => [ 'url' => $fileInfo['url'], 'extension' => $fileInfo["type"], 'size' => $fileInfo["size"], 'type' => $this->getFileType(trim($fileInfo['type'],".")) ] ]; } else { $data = [ 'code' => 1, 'msg' => $fileInfo["state"] ]; } return $this->responseHandler($data); } //上传文件 public function actionFile() { try { if(!\Yii::$app->request->isPost){ $data = [ 'code' => 1, 'msg' => "Invalid Request" ]; return $this->responseHandler($data); } $action = "uploadfile"; $fileInfo = $this->uploadFile($action); if($fileInfo["state"] == "SUCCESS"){ $data = [ 'code' => 0, 'msg' => 'success', 'data' => [ 'url' => $fileInfo['url'], 'extension' => $fileInfo["type"], 'size' => $fileInfo["size"], 'type' => $this->getFileType(trim($fileInfo['type'],".")) ] ]; } else { $data = [ 'code' => 1, 'msg' => $fileInfo["state"] ]; } }catch (\Exception $e){ $data = [ 'code' => 1, 'msg' => $e->getMessage() ]; } return $this->responseHandler($data); } //上传视频 public function actionVideoFile() { if(!\Yii::$app->request->isPost){ $data = [ 'code' => 1, 'msg' => "Invalid Request" ]; } $action = "uploadvideo"; $fileInfo = $this->uploadFile($action); if($fileInfo["state"] == "SUCCESS"){ $data = [ 'code' => 0, 'msg' => 'success', 'data' => [ 'url' => $fileInfo['url'], 'extension' => $fileInfo["type"], 'size' => $fileInfo["size"], 'type' => $this->getFileType(trim($fileInfo['type'],".")) ] ]; } else { $data = [ 'code' => 1, 'msg' => $fileInfo["state"] ]; } return $this->responseHandler($data); } /** * @TODO 扩展上传至第三方存储 * 文件上传 */ private function uploadFile($action){ //获取上传配置 $uploadConfig = $this->getUploadConfig($action); $path = $uploadConfig["path"]; $_config = $uploadConfig["config"]; /* 上传配置 */ $base64 = "upload"; switch ($action) { case 'uploadimage': $_config['imagePathFormat'] = $path . $_config['imagePathFormat']; $config = array( "pathFormat" => $_config['imagePathFormat'], "maxSize" => $_config['imageMaxSize'], "allowFiles" => $_config['imageAllowFiles'] ); $fieldName = $_config['imageFieldName']; break; case 'uploadscrawl': $_config['scrawlPathFormat'] = $path . $_config['scrawlPathFormat']; $config = array( "pathFormat" => $_config['scrawlPathFormat'], "maxSize" => $_config['scrawlMaxSize'], "allowFiles" => $_config['scrawlAllowFiles'], "oriName" => "scrawl.png" ); $fieldName = $_config['scrawlFieldName']; $base64 = "base64"; break; case 'uploadvideo': $_config['videoPathFormat'] = $path . $_config['videoPathFormat']; $config = array( "pathFormat" => $_config['videoPathFormat'], "maxSize" => $_config['videoMaxSize'], "allowFiles" => $_config['videoAllowFiles'] ); $fieldName = $_config['videoFieldName']; break; case 'uploadimageUnion': #########2022/06/10##################### $_config['imagePathFormat'] = $path . $_config['imagePathFormat']; $config = array( "pathFormat" => $_config['imagePathFormat'], "maxSize" => $_config['imageMaxSize_union'], "allowFiles" => $_config['imageAllowFiles'] ); $fieldName = $_config['imageFieldName']; break; case 'uploadfile': default: $_config['filePathFormat'] = $path . $_config['filePathFormat']; $config = array( "pathFormat" => $_config['filePathFormat'], "maxSize" => $_config['fileMaxSize'], "allowFiles" => $_config['fileAllowFiles'] ); $fieldName = $_config['fileFieldName']; break; } /* 生成上传实例对象并完成上传 */ $up = new Uploader($fieldName, $config, $base64); /** * 得到上传文件所对应的各个参数,数组结构 * array( * "state" => "", //上传状态,上传成功时必须返回"SUCCESS" * "url" => "", //返回的地址 * "title" => "", //新文件名 * "original" => "", //原始文件名 * "type" => "" //文件类型 * "size" => "", //文件大小 * ) */ /* 返回数据 */ $fileInfo = $up->getFileInfo(); if($fileInfo["state"] == "SUCCESS"){ $this->imageCompress($fileInfo); $model = new UploadFile(); $model->cx_mch_id = $this->cx_mch_id; $model->user_id = Model::getUserId(); $model->file_url = $fileInfo["url"]; $model->extension = trim($fileInfo["type"],"."); $model->type = $this->getFileType($model->extension); $model->size = $fileInfo["size"]; $model->group_id = \Yii::$app->request->get("group_id"); $model->group_id = $model->group_id ? $model->group_id : 0; $model->save(); } return $fileInfo; } private function imageCompress(&$fileInfo) { $filetype = $this->getFileType(trim($fileInfo["type"],".")); if($filetype != "image") return; $imageCompressConfig = $this->getImageCompressConfig(); $filename = trim($fileInfo["url"],'/'); if($imageCompressConfig['imageCompressEnable'] && file_exists($filename)){ try{ $gumletImagic = new ImageResize($filename); $gumletImagic->resizeToLongSide($imageCompressConfig['imageCompressBorder']); $gumletImagic->save($filename); clearstatcache(); } catch (ImageResizeException $ex){ } } $fileInfo["size"] = filesize($filename); } private function mkDir($dir, $mode = 0777) { return is_dir($dir) or $this->mkDir(dirname($dir), $mode) and mkdir($dir, $mode); } private function getImageCompressConfig() { $config = []; $imageCompressEnable = \Yii::$app->request->get('imageCompressEnable'); if($imageCompressEnable !== null){ $config['imageCompressEnable'] = $imageCompressEnable == 1 ? true : false; } else { $config['imageCompressEnable'] = $this->uploadConfig['uploadFile']['imageCompressEnable']; } $imageCompressBorder = \Yii::$app->request->get('imageCompressBorder'); if($imageCompressBorder !== null && is_numeric($imageCompressBorder)){ $imageCompressBorder = (int)$imageCompressBorder; $config['imageCompressBorder'] = $imageCompressBorder; } else { $config['imageCompressBorder'] = $this->uploadConfig['uploadFile']['imageCompressBorder']; } return $config; } private function getFileType($extension) { $type_list = [ 'image' => ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'ico'], 'video' => ['mp4', 'flv', 'ogg', 'mov',], ]; foreach ($type_list as $type => $exs) { if (in_array($extension, $exs)) { return $type; } } return ''; } /** * 获取已经上传的文件列表 */ private function getFileList($action){ //获取上传配置 $uploadConfig = $this->getUploadConfig($action); $_path = $uploadConfig["path"]; $_config = $uploadConfig["config"]; /* 判断类型 */ switch ($action) { /* 列出文件 */ case 'listfile': $_config['fileManagerListPath'] = $_path .$_config['fileManagerListPath']; $allowFiles = $_config['fileManagerAllowFiles']; $listSize = $_config['fileManagerListSize']; $path = $_config['fileManagerListPath']; break; /* 列出图片 */ case 'listimage': default: $_config['imageManagerListPath'] = $_path . $_config['imageManagerListPath']; $allowFiles = $_config['imageManagerAllowFiles']; $listSize = $_config['imageManagerListSize']; $path = $_config['imageManagerListPath']; } $allowFiles = substr(str_replace(".", "|", join("", $allowFiles)), 1); /* 获取参数 */ $size = isset($_GET['size']) ? htmlspecialchars($_GET['size']) : $listSize; $start = isset($_GET['start']) ? htmlspecialchars($_GET['start']) : 0; $end = $start + $size; /* 获取文件列表 */ $path = $_SERVER['DOCUMENT_ROOT'] . (substr($path, 0, 1) == "/" ? "":"/") . $path; $files = $this->getfiles($path, $allowFiles); if (!count($files)) { return json_encode(array( "state" => "no match file", "list" => array(), "start" => $start, "total" => count($files) )); } /* 获取指定范围的列表 */ $len = count($files); for ($i = min($end, $len) - 1, $list = array(); $i < $len && $i >= 0 && $i >= $start; $i--){ $list[] = $files[$i]; } //倒序 //for ($i = $end, $list = array(); $i < $len && $i < $end; $i++){ // $list[] = $files[$i]; //} /* 返回数据 */ $result = json_encode(array( "state" => "SUCCESS", "list" => $list, "start" => $start, "total" => count($files) )); return $result; } /** * 遍历获取目录下的指定类型的文件 * @param $path * @param array $files * @return array */ private function getfiles($path, $allowFiles, &$files = array()) { if (!is_dir($path)) return null; if(substr($path, strlen($path) - 1) != '/') $path .= '/'; $handle = opendir($path); while (false !== ($file = readdir($handle))) { if ($file != '.' && $file != '..') { $path2 = $path . $file; if (is_dir($path2)) { $this->getfiles($path2, $allowFiles, $files); } else { if (preg_match("/\.(".$allowFiles.")$/i", $file)) { $files[] = array( 'url'=> substr($path2, strlen($_SERVER['DOCUMENT_ROOT'])), 'mtime'=> filemtime($path2) ); } } } } return $files; } /** * 获取上传路径前缀,及配置信息 */ private function getUploadConfig($action){ $path = UploadHelper::getUploadPath($this->cx_mch_id); $config = $this->uploadConfig['uploadFile']; return array( "path" => $path, "config" => $config ); } /** * 抓取远程图片 */ private function crawlerImage($action) { set_time_limit(0); //获取上传配置 $uploadConfig = $this->getUploadConfig($action); $_path = $uploadConfig["path"]; $_config = $uploadConfig["config"]; /* 上传配置 */ $_config['catcherPathFormat'] = $_path . $_config['catcherPathFormat']; $config = array( "pathFormat" => $_config['catcherPathFormat'], "maxSize" => $_config['catcherMaxSize'], "allowFiles" => $_config['catcherAllowFiles'], "oriName" => "remote.png" ); $fieldName = $_config['catcherFieldName']; /* 抓取远程图片 */ $list = array(); if (isset($_POST[$fieldName])) { $source = $_POST[$fieldName]; } else { $source = $_GET[$fieldName]; } foreach ($source as $imgUrl) { $item = new Uploader($imgUrl, $config, "remote"); $info = $item->getFileInfo(); array_push($list, array( "state" => $info["state"], "url" => $info["url"], "size" => $info["size"], "title" => htmlspecialchars($info["title"]), "original" => htmlspecialchars($info["original"]), "source" => htmlspecialchars($imgUrl) )); } /* 返回抓取数据 */ return json_encode(array( 'state'=> count($list) ? 'SUCCESS': 'ERROR', 'list'=> $list )); } public function actionVideo() { set_time_limit (0); $params = \Yii::$app->request->post(); $tempDir = './temp/upload/video/chunks/'.date('Ymd',time()) . '/' . md5($params['name']); if(!file_exists($tempDir)) $this->mk_dir($tempDir); if(!isset($params['chunk'])){ $params['chunk'] = 0; } if(!isset($params['chunks'])){ $params['chunks'] = 1; } //获取上传配置 $action = 'uploadvideo'; $uploadConfig = $this->getUploadConfig($action); $config = array( "pathFormat" => $tempDir . '/' .$params['chunk'], "maxSize" => $uploadConfig['config']['videoMaxSize'], "allowFiles" => $uploadConfig['config']['videoAllowFiles'] ); $base64 = "upload"; /* 生成上传实例对象并完成上传 */ $up = new Uploader('file', $config, $base64); $fileInfo = $up->getFileInfo(); $chunk = strval($params['chunk']); $chunkCount = strval($params['chunks']); if($chunk + 1 == $chunkCount){ //合并 $targetDir = './upload/video/'.date('Ymd',time()). '/' . md5($params['name']); if(!file_exists($targetDir)) $this->mk_dir($targetDir); $finalName = $targetDir . $fileInfo['type']; if(file_exists($finalName)) unlink($finalName); $file = fopen($finalName, 'wb'); for($index = 0; $index < $chunkCount; $index++){ $tmpFile = $tempDir . '/'. $index . $fileInfo['type']; $chunkFile = fopen($tmpFile, 'rb'); $content = fread($chunkFile, filesize($tmpFile)); fclose($chunkFile); fwrite($file, $content); //删除chunk文件 unlink($tmpFile); } fclose($file); //删除chunk文件夹 rmdir($targetDir); $fileInfo['url'] = $finalName; } /* 返回数据 */ \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; return $fileInfo; } private function mk_dir($dir,$mode = 0777) { return is_dir($dir) or $this->mk_dir(dirname($dir),$mode) and mkdir($dir,$mode); } //上传图片 public function actionUnionImage() { if(!\Yii::$app->request->isPost){ $data = [ 'code' => 1, 'msg' => "Invalid Request" ]; return $this->responseHandler($data); } $action = "uploadimageUnion"; $fileInfo = $this->uploadFile($action); if($fileInfo["state"] == "SUCCESS"){ $data = [ 'code' => 0, 'msg' => 'success', 'data' => [ 'url' => $fileInfo['url'], 'extension' => $fileInfo["type"], 'size' => $fileInfo["size"], 'type' => $this->getFileType(trim($fileInfo['type'],".")) ] ]; } else { $data = [ 'code' => 1, 'msg' => $fileInfo["state"] ]; } return $this->responseHandler($data); } }