427 lines
14 KiB
PHP
427 lines
14 KiB
PHP
<?php
|
|
// +----------------------------------------------------------------------
|
|
// | YwxApp [ WE CAN DO IT JUST THINK ]
|
|
// +----------------------------------------------------------------------
|
|
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
|
|
// +----------------------------------------------------------------------
|
|
// | Author: ywxapp<admin@ywxapp.cn>
|
|
// +----------------------------------------------------------------------
|
|
namespace ywxapp\services;
|
|
|
|
use think\facade\Filesystem;
|
|
use think\facade\Request;
|
|
|
|
/**
|
|
* UEditorService 类
|
|
*
|
|
* @author ywxapp <admin@ywxapp.cn>
|
|
*/
|
|
class UEditorService
|
|
{
|
|
|
|
public function __construct()
|
|
{
|
|
header("Access-Control-Allow-Origin: *");
|
|
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");
|
|
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
|
|
|
|
if (request()->method() == 'OPTIONS') {
|
|
exit();
|
|
}
|
|
}
|
|
/**
|
|
* UEditor 后端接口
|
|
*/
|
|
public function index()
|
|
{
|
|
$action = Request::param('action');
|
|
|
|
switch ($action) {
|
|
case 'config':
|
|
$result = $this->getConfig();
|
|
break;
|
|
case 'uploadimage':
|
|
$result = $this->uploadImage();
|
|
break;
|
|
case 'uploadscrawl':
|
|
$result = $this->uploadScrawl();
|
|
break;
|
|
case 'uploadvideo':
|
|
$result = $this->uploadVideo();
|
|
break;
|
|
case 'uploadfile':
|
|
$result = $this->uploadFile();
|
|
break;
|
|
case 'listimage':
|
|
$result = $this->listImage();
|
|
break;
|
|
case 'listfile':
|
|
$result = $this->listFile();
|
|
break;
|
|
case 'catchimage':
|
|
$result = $this->catchImage();
|
|
break;
|
|
default:
|
|
$result = [
|
|
'state' => '请求地址出错',
|
|
];
|
|
break;
|
|
}
|
|
|
|
return json($result);
|
|
}
|
|
|
|
/**
|
|
* 获取配置
|
|
*/
|
|
private function getConfig()
|
|
{
|
|
return [
|
|
/* 上传图片配置项 */
|
|
"imageActionName" => "uploadimage",
|
|
"imageFieldName" => "upfile",
|
|
"imageMaxSize" => 2048000,
|
|
"imageAllowFiles" => [".png", ".jpg", ".jpeg", ".gif", ".bmp"],
|
|
"imageCompressEnable" => true,
|
|
"imageCompressBorder" => 1600,
|
|
"imageInsertAlign" => "none",
|
|
"imageUrlPrefix" => "",
|
|
|
|
/* 涂鸦图片上传配置项 */
|
|
"scrawlActionName" => "uploadscrawl",
|
|
"scrawlFieldName" => "upfile",
|
|
"scrawlMaxSize" => 2048000,
|
|
"scrawlUrlPrefix" => "",
|
|
"scrawlInsertAlign" => "none",
|
|
|
|
/* 截图工具上传 */
|
|
"snapscreenActionName" => "uploadimage",
|
|
"snapscreenUrlPrefix" => "",
|
|
"snapscreenInsertAlign" => "none",
|
|
|
|
/* 抓取远程图片配置 */
|
|
"catcherLocalDomain" => ["127.0.0.1", "localhost"],
|
|
"catcherActionName" => "catchimage",
|
|
"catcherFieldName" => "source",
|
|
"catcherUrlPrefix" => "",
|
|
"catcherMaxSize" => 2048000,
|
|
"catcherAllowFiles" => [".png", ".jpg", ".jpeg", ".gif", ".bmp"],
|
|
|
|
/* 上传视频配置 */
|
|
"videoActionName" => "uploadvideo",
|
|
"videoFieldName" => "upfile",
|
|
"videoMaxSize" => 102400000,
|
|
"videoUrlPrefix" => "",
|
|
"videoAllowFiles" => [
|
|
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
|
|
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
|
|
],
|
|
|
|
/* 上传文件配置 */
|
|
"fileActionName" => "uploadfile",
|
|
"fileFieldName" => "upfile",
|
|
"fileMaxSize" => 51200000,
|
|
"fileUrlPrefix" => "",
|
|
"fileAllowFiles" => [
|
|
".png", ".jpg", ".jpeg", ".gif", ".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",
|
|
],
|
|
|
|
/* 列出指定目录下的图片 */
|
|
"imageManagerActionName" => "listimage",
|
|
"imageManagerListPath" => "/upload/image/",
|
|
"imageManagerListSize" => 20,
|
|
"imageManagerUrlPrefix" => "",
|
|
"imageManagerInsertAlign" => "none",
|
|
"imageManagerAllowFiles" => [".png", ".jpg", ".jpeg", ".gif", ".bmp"],
|
|
|
|
/* 列出指定目录下的文件 */
|
|
"fileManagerActionName" => "listfile",
|
|
"fileManagerListPath" => "/upload/file/",
|
|
"fileManagerListSize" => 20,
|
|
"fileManagerUrlPrefix" => "",
|
|
"fileManagerAllowFiles" => [
|
|
".png", ".jpg", ".jpeg", ".gif", ".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",
|
|
],
|
|
|
|
/* 配置项 */
|
|
"imageUrlPrefix" => Request::domain() , /* 图片访问路径前缀 */
|
|
"scrawlUrlPrefix" => Request::domain() , /* 涂鸦访问路径前缀 */
|
|
"snapscreenUrlPrefix" => Request::domain() , /* 截图访问路径前缀 */
|
|
"catcherUrlPrefix" => Request::domain() , /* 图片访问路径前缀 */
|
|
"videoUrlPrefix" => Request::domain() , /* 视频访问路径前缀 */
|
|
"fileUrlPrefix" => Request::domain() , /* 文件访问路径前缀 */
|
|
"imagePathFormat" => "/uploads/images/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
|
|
"scrawlPathFormat" => "/uploads/scrawl/{yyyy}{mm}{dd}/{time}{rand:6}", /* 涂鸦上传保存路径 */
|
|
"snapscreenPathFormat" => "/uploads/images/{yyyy}{mm}{dd}/{time}{rand:6}", /* 截图上传保存路径 */
|
|
"catcherPathFormat" => "/uploads/images/{yyyy}{mm}{dd}/{time}{rand:6}", /* 抓取图片上传保存路径 */
|
|
"videoPathFormat" => "/uploads/videos/{yyyy}{mm}{dd}/{time}{rand:6}", /* 视频上传保存路径 */
|
|
"filePathFormat" => "/uploads/files/{yyyy}{mm}{dd}/{time}{rand:6}", /* 文件上传保存路径 */
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 上传图片
|
|
*/
|
|
private function uploadImage()
|
|
{
|
|
return $this->upload('image');
|
|
}
|
|
|
|
/**
|
|
* 上传涂鸦
|
|
*/
|
|
private function uploadScrawl()
|
|
{
|
|
$file = Request::post('upfile');
|
|
if (empty($file)) {
|
|
return ['state' => '上传文件为空'];
|
|
}
|
|
|
|
// 生成文件名
|
|
$filename = date('Ymd') . '/' . uniqid() . '.png';
|
|
|
|
// 保存路径
|
|
$savePath = 'uploads/scrawl/' . $filename;
|
|
$fullPath = public_path() . $savePath;
|
|
|
|
// 确保目录存在
|
|
$dir = dirname($fullPath);
|
|
if (! is_dir($dir)) {
|
|
mkdir($dir, 0755, true);
|
|
}
|
|
|
|
// 解码并保存base64图片
|
|
$img = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $file));
|
|
file_put_contents($fullPath, $img);
|
|
|
|
return [
|
|
"state" => "SUCCESS",
|
|
"url" => Request::domain() . '/' . $savePath,
|
|
"title" => $filename,
|
|
"original" => "scrawl.png",
|
|
"type" => ".png",
|
|
"size" => strlen($img),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 上传视频
|
|
*/
|
|
private function uploadVideo()
|
|
{
|
|
return $this->upload('video');
|
|
}
|
|
|
|
/**
|
|
* 上传文件
|
|
*/
|
|
private function uploadFile()
|
|
{
|
|
return $this->upload('file');
|
|
}
|
|
|
|
/**
|
|
* 通用上传方法
|
|
*/
|
|
private function upload($type)
|
|
{
|
|
$file = Request::file('upfile');
|
|
if (empty($file)) {
|
|
return ['state' => '上传文件为空'];
|
|
}
|
|
|
|
// 验证文件
|
|
$config = $this->getConfig();
|
|
$maxSize = $config[$type . 'MaxSize'];
|
|
$allowFiles = $config[$type . 'AllowFiles'];
|
|
|
|
try {
|
|
$validate = [
|
|
'size' => $maxSize,
|
|
'ext' => implode(',', array_map(function ($ext) {
|
|
return ltrim($ext, '.');
|
|
}, $allowFiles)),
|
|
];
|
|
|
|
$savename = Filesystem::disk('public')->putFile('uploads/' . $type, $file);
|
|
|
|
return [
|
|
"state" => "SUCCESS",
|
|
"url" => '/storage/' . $savename,
|
|
"title" => basename($savename),
|
|
"original" => $file->getOriginalName(),
|
|
"type" => '.' . $file->extension(),
|
|
"size" => $file->getSize(),
|
|
];
|
|
} catch (\Exception $e) {
|
|
return ['state' => $e->getMessage()];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 列出图片
|
|
*/
|
|
private function listImage()
|
|
{
|
|
return $this->listFiles('image');
|
|
}
|
|
|
|
/**
|
|
* 列出文件
|
|
*/
|
|
private function listFile()
|
|
{
|
|
return $this->listFiles('file');
|
|
}
|
|
|
|
/**
|
|
* 列出文件通用方法
|
|
*/
|
|
private function listFiles($type)
|
|
{
|
|
$config = $this->getConfig();
|
|
$allowFiles = $config[$type . 'ManagerAllowFiles'];
|
|
$listSize = $config[$type . 'ManagerListSize'];
|
|
$path = $config[$type . 'ManagerListPath'];
|
|
|
|
$start = Request::param('start', 0);
|
|
$size = Request::param('size', $listSize);
|
|
|
|
$files = $this->getFiles(public_path() . $path, $allowFiles);
|
|
if (! count($files)) {
|
|
return [
|
|
"state" => "no match file",
|
|
"list" => [],
|
|
"start" => $start,
|
|
"total" => 0,
|
|
];
|
|
}
|
|
|
|
// 排序
|
|
usort($files, function ($a, $b) {
|
|
return strcmp($a['mtime'], $b['mtime']);
|
|
});
|
|
|
|
// 分页
|
|
$files = array_slice($files, $start, $size);
|
|
|
|
return [
|
|
"state" => "SUCCESS",
|
|
"list" => $files,
|
|
"start" => $start,
|
|
"total" => count($files),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 获取目录下的文件
|
|
*/
|
|
private function getFiles($path, $allowFiles, &$files = [])
|
|
{
|
|
if (! is_dir($path)) {
|
|
return [];
|
|
}
|
|
|
|
$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("/\.(" . str_replace('.', '', implode('|', $allowFiles)) . ")$/i", $file)) {
|
|
$files[] = [
|
|
'url' => Request::domain() . str_replace(public_path(), '', $path2),
|
|
'mtime' => filemtime($path2),
|
|
];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $files;
|
|
}
|
|
|
|
/**
|
|
* 抓取远程图片
|
|
*/
|
|
private function catchImage()
|
|
{
|
|
$sources = Request::param('source', []);
|
|
if (empty($sources)) {
|
|
return ['state' => '参数错误:没有指定抓取源'];
|
|
}
|
|
|
|
$list = [];
|
|
foreach ($sources as $imgUrl) {
|
|
// 验证域名
|
|
$config = $this->getConfig();
|
|
$domain = parse_url($imgUrl, PHP_URL_HOST);
|
|
if (! in_array($domain, $config['catcherLocalDomain'])) {
|
|
$list[] = [
|
|
'state' => '抓取远程图片失败,域名不允许',
|
|
'url' => $imgUrl,
|
|
'source' => $imgUrl,
|
|
];
|
|
continue;
|
|
}
|
|
|
|
// 获取图片
|
|
$imgContent = file_get_contents($imgUrl);
|
|
if ($imgContent === false) {
|
|
$list[] = [
|
|
'state' => '抓取远程图片失败',
|
|
'url' => $imgUrl,
|
|
'source' => $imgUrl,
|
|
];
|
|
continue;
|
|
}
|
|
|
|
// 验证图片
|
|
$imgInfo = getimagesizefromstring($imgContent);
|
|
if (! $imgInfo) {
|
|
$list[] = [
|
|
'state' => '不是有效的图片文件',
|
|
'url' => $imgUrl,
|
|
'source' => $imgUrl,
|
|
];
|
|
continue;
|
|
}
|
|
|
|
// 生成文件名
|
|
$ext = image_type_to_extension($imgInfo[2]);
|
|
$filename = date('Ymd') . '/' . uniqid() . $ext;
|
|
$savePath = 'uploads/images/' . $filename;
|
|
$fullPath = public_path() . $savePath;
|
|
|
|
// 确保目录存在
|
|
$dir = dirname($fullPath);
|
|
if (! is_dir($dir)) {
|
|
mkdir($dir, 0755, true);
|
|
}
|
|
|
|
// 保存文件
|
|
file_put_contents($fullPath, $imgContent);
|
|
|
|
$list[] = [
|
|
'state' => 'SUCCESS',
|
|
'url' => Request::domain() . '/' . $savePath,
|
|
'source' => $imgUrl,
|
|
];
|
|
}
|
|
|
|
return [
|
|
'state' => count($list) ? 'SUCCESS' : 'ERROR',
|
|
'list' => $list,
|
|
];
|
|
}
|
|
}
|