469 lines
18 KiB
PHP
Executable File
469 lines
18 KiB
PHP
Executable File
<?php
|
|
|
|
namespace app\admin\controller;
|
|
|
|
use think\Lang;
|
|
use think\Loader;
|
|
use think\Config;
|
|
use image\Image;
|
|
|
|
class Ueditor extends BaseController {
|
|
|
|
private $basePath = '/';
|
|
private $saveDirectory = 'default';
|
|
private $config; //配置信息
|
|
|
|
public function __construct() {
|
|
parent::__construct();
|
|
date_default_timezone_set("Asia/Shanghai");
|
|
$this->docDir = $this->request->server('DOCUMENT_ROOT');
|
|
$this->rootDir = $this->request->root();
|
|
$this->basePath = $this->docDir . $this->rootDir . '/uploads';
|
|
$this->saveDirectory = 'temp';
|
|
error_reporting(E_ERROR | E_WARNING);
|
|
Config::set('url_common_param', true);
|
|
header("Content-Type: text/html; charset=utf-8");
|
|
}
|
|
|
|
//上传文件
|
|
private function upFile($fileField, $config = array()) {
|
|
$result = array('state' => "ERROR_UNKNOWN 未知错误");
|
|
$file = $this->request->file($fileField);
|
|
if (empty($file)) {
|
|
$file = $this->request->file('upfile');
|
|
}
|
|
// $error = $this->validate(
|
|
// ['file' => $file], ['file' => 'image|fileSize:40000000|fileExt:jpg,jpeg,gif,png'], ['file.image' => '上传文件必须为图片', 'file.fileSize' => '上传文件过大', 'file.fileExt' => '上传文件后缀名必须为jpg,jpeg,gif,png']
|
|
// );
|
|
$error = true;
|
|
if (true !== $error || empty($file)) {
|
|
return json_encode(['state' => "ERROR " . $error]);
|
|
} else {
|
|
// 移动到框架应用根目录/public/uploads/ 目录下
|
|
$saveDirectory = $this->saveDirectory . '/' . date('Y/md') . '/';
|
|
// 使用自定义的文件保存规则
|
|
$info = $file->rule(function($file) {
|
|
return md5(mt_rand());
|
|
})->move($this->basePath . '/' . $saveDirectory);
|
|
if ($info) {
|
|
$result = array(
|
|
'state' => 'SUCCESS',
|
|
'url' => '/uploads/' . $saveDirectory . $info->getFilename(),
|
|
'title' => $info->getFilename(),
|
|
'original' => $info->getFilename(),
|
|
'type' => '.' . $info->getExtension(),
|
|
'size' => $info->getSize(),
|
|
);
|
|
//图片加水印
|
|
$ext = strtolower($info->getExtension());
|
|
if (in_array($ext, ['gif', 'jpg', 'jpeg', 'png', 'bmp'])) {
|
|
$this->watermark('/uploads/' . $saveDirectory . $info->getFilename());
|
|
}
|
|
} else {
|
|
$result['state'] = 'ERROR ' . $file->getError();
|
|
}
|
|
}
|
|
return json_encode($result);
|
|
}
|
|
|
|
/*
|
|
* 处理base64编码的图片上传
|
|
* 例如:涂鸦图片上传
|
|
*/
|
|
|
|
private function upBase64($fileField, $config) {
|
|
$base64Data = $this->request->post($fileField);
|
|
$img = base64_decode($base64Data);
|
|
$dirname = $this->basePath . '/' . $this->saveDirectory . '/';
|
|
$file['filesize'] = strlen($img);
|
|
$file['oriName'] = $config['oriName'];
|
|
$file['ext'] = strtolower(strrchr($config['oriName'], '.'));
|
|
$file['name'] = uniqid() . $file['ext'];
|
|
$file['fullName'] = $dirname . $file['name'];
|
|
$fullName = $file['fullName'];
|
|
//检查文件大小是否超出限制
|
|
if ($file['filesize'] >= ($config["maxSize"])) {
|
|
$data = array(
|
|
'state' => '文件大小超出网站限制',
|
|
);
|
|
return json_encode($data);
|
|
}
|
|
//创建目录失败
|
|
if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) {
|
|
$data = array(
|
|
'state' => '目录创建失败',
|
|
);
|
|
return json_encode($data);
|
|
} else if (!is_writeable($dirname)) {
|
|
$data = array(
|
|
'state' => '目录没有写权限',
|
|
);
|
|
return json_encode($data);
|
|
}
|
|
//移动文件
|
|
if (!(file_put_contents($fullName, $img) && file_exists($fullName))) { //移动失败
|
|
$data = array(
|
|
'state' => '写入文件内容错误',
|
|
);
|
|
} else { //移动成功
|
|
$data = array(
|
|
'state' => 'SUCCESS',
|
|
'url' => substr($file['fullName'], 1),
|
|
'title' => $file['name'],
|
|
'original' => $file['oriName'],
|
|
'type' => $file['ext'],
|
|
'size' => $file['filesize'],
|
|
);
|
|
}
|
|
return json_encode($data);
|
|
}
|
|
|
|
//列出图片
|
|
private function listFile($allowFiles, $listSize, $get) {
|
|
$dirname = $this->basePath . '/' . $this->saveDirectory . '/';
|
|
$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 = $dirname;
|
|
$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;
|
|
}
|
|
|
|
/**
|
|
* 拉取远程图片
|
|
* @return mixed
|
|
*/
|
|
private function saveRemotess($fieldName, $config) {
|
|
$imgUrl = htmlspecialchars($fieldName);
|
|
$imgUrl = str_replace("&", "&", $imgUrl);
|
|
//http开头验证
|
|
if (strpos($imgUrl, "http") !== 0) {
|
|
$data = array(
|
|
'state' => '链接不是http链接',
|
|
);
|
|
return json_encode($data);
|
|
}
|
|
//获取请求头并检测死链
|
|
$heads = get_headers($imgUrl);
|
|
if (!(stristr($heads[0], "200") && stristr($heads[0], "OK"))) {
|
|
$data = array(
|
|
'state' => '链接不可用',
|
|
);
|
|
return json_encode($data);
|
|
}
|
|
//格式验证(扩展名验证和Content-Type验证)
|
|
$fileType = strtolower(strrchr($imgUrl, '.'));
|
|
if (!in_array($fileType, $config['allowFiles']) || stristr($heads['Content-Type'], "image")) {
|
|
$data = array(
|
|
'state' => '链接contentType不正确',
|
|
);
|
|
return json_encode($data);
|
|
}
|
|
//打开输出缓冲区并获取远程图片
|
|
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();
|
|
preg_match("/[\/]([^\/]*)[\.]?[^\.\/]*$/", $imgUrl, $m);
|
|
$dirname = $this->basePath . '/' . $this->saveDirectory . '/' . date('Y/md') . '/';
|
|
$file['oriName'] = $m ? $m[1] : "";
|
|
$file['filesize'] = strlen($img);
|
|
$file['ext'] = strtolower(strrchr($config['oriName'], '.'));
|
|
$file['name'] = md5(mt_rand()) . $file['ext'];
|
|
$file['fullName'] = $dirname . $file['name'];
|
|
$fullName = $file['fullName'];
|
|
//检查文件大小是否超出限制
|
|
if ($file['filesize'] >= ($config["maxSize"])) {
|
|
$data = array(
|
|
'state' => '文件大小超出网站限制',
|
|
);
|
|
return json_encode($data);
|
|
}
|
|
//创建目录失败
|
|
if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) {
|
|
$data = array(
|
|
'state' => '目录创建失败',
|
|
);
|
|
return json_encode($data);
|
|
} else if (!is_writeable($dirname)) {
|
|
$data = array(
|
|
'state' => '目录没有写权限',
|
|
);
|
|
return json_encode($data);
|
|
}
|
|
//移动文件
|
|
if (!(file_put_contents($fullName, $img) && file_exists($fullName))) { //移动失败
|
|
$data = array(
|
|
'state' => '写入文件内容错误',
|
|
);
|
|
return json_encode($data);
|
|
} else { //移动成功
|
|
$data = array(
|
|
'state' => 'SUCCESS',
|
|
'url' => substr($file['fullName'], strlen($this->docDir . $this->rootDir)),
|
|
'title' => $file['name'],
|
|
'original' => $file['oriName'],
|
|
'type' => $file['ext'],
|
|
'size' => $file['filesize'],
|
|
);
|
|
}
|
|
|
|
return json_encode($data);
|
|
}
|
|
|
|
/**
|
|
* 拉取远程图片
|
|
* @return mixed
|
|
*/
|
|
private function saveRemote($fileField, $config = array()) {
|
|
$imgUrl = htmlspecialchars($fileField);
|
|
$imgUrl = str_replace("&", "&", $imgUrl);
|
|
//http开头验证
|
|
if (strpos($imgUrl, "http") !== 0) {
|
|
$data = array(
|
|
'state' => '链接不是http链接',
|
|
);
|
|
return json_encode($data);
|
|
}
|
|
preg_match('/(^https*:\/\/[^:\/]+)/', $imgUrl, $matches);
|
|
$host_with_protocol = count($matches) > 1 ? $matches[1] : '';
|
|
// 判断是否是合法 url
|
|
if (!filter_var($host_with_protocol, FILTER_VALIDATE_URL)) {
|
|
$data = array(
|
|
'state' => 'INVALID_URL',
|
|
);
|
|
return json_encode($data);
|
|
}
|
|
preg_match('/^https*:\/\/(.+)/', $host_with_protocol, $matches);
|
|
$host_without_protocol = count($matches) > 1 ? $matches[1] : '';
|
|
// 此时提取出来的可能是 ip 也有可能是域名,先获取 ip
|
|
$ip = gethostbyname($host_without_protocol);
|
|
// 判断是否是私有 ip
|
|
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
|
|
$data = array(
|
|
'state' => 'INVALID_IP',
|
|
);
|
|
return json_encode($data);
|
|
}
|
|
//获取请求头并检测死链
|
|
$heads = get_headers($imgUrl);
|
|
if (!(stristr($heads[0], "200") && stristr($heads[0], "OK"))) {
|
|
$data = array(
|
|
'state' => '链接不可用',
|
|
);
|
|
return json_encode($data);
|
|
}
|
|
//格式验证(扩展名验证和Content-Type验证)
|
|
$fileType = strtolower(strrchr($imgUrl, '.'));
|
|
if (!in_array($fileType, $config['allowFiles']) || stristr($heads['Content-Type'], "image")) {
|
|
$data = array(
|
|
'state' => '链接contentType不正确',
|
|
);
|
|
return json_encode($data);
|
|
}
|
|
//打开输出缓冲区并获取远程图片
|
|
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();
|
|
preg_match("/[\/]([^\/]*)[\.]?[^\.\/]*$/", $imgUrl, $m);
|
|
$dirname = $this->basePath . '/' . $this->saveDirectory . '/' . date('Y/md') . '/';
|
|
$file['oriName'] = $m ? $m[1] : "";
|
|
$file['filesize'] = strlen($img);
|
|
$file['ext'] = strtolower(strrchr($config['oriName'], '.'));
|
|
$file['name'] = md5(mt_rand()) . $file['ext'];
|
|
$file['fullName'] = $dirname . $file['name'];
|
|
$fullName = $file['fullName'];
|
|
//检查文件大小是否超出限制
|
|
if ($file['filesize'] >= ($config["maxSize"])) {
|
|
$data = array(
|
|
'state' => '文件大小超出网站限制',
|
|
);
|
|
return json_encode($data);
|
|
}
|
|
//创建目录失败
|
|
if (!is_dir($dirname) && !mkdir($dirname, 0777, true)) {
|
|
$data = array(
|
|
'state' => '目录创建失败',
|
|
);
|
|
return json_encode($data);
|
|
} else if (!is_writeable($dirname)) {
|
|
$data = array(
|
|
'state' => '目录没有写权限',
|
|
);
|
|
return json_encode($data);
|
|
}
|
|
//移动文件
|
|
if (!(file_put_contents($fullName, $img) && is_file($fullName))) { //移动失败
|
|
$data = array(
|
|
'state' => '写入文件内容错误',
|
|
);
|
|
return json_encode($data);
|
|
} else { //移动成功
|
|
//$this->watermark(substr($file['fullName'], strlen($this->docDir . $this->rootDir)));
|
|
$data = array(
|
|
'state' => 'SUCCESS',
|
|
'url' => substr($file['fullName'], strlen($this->docDir . $this->rootDir)),
|
|
'title' => $file['name'],
|
|
'original' => $file['oriName'],
|
|
'type' => $file['ext'],
|
|
'size' => $file['filesize'],
|
|
);
|
|
}
|
|
|
|
return json_encode($data);
|
|
}
|
|
|
|
public function watermark($return_url = '/uploads/nopic.jpg') {
|
|
$iswatermark = Config::get('watermark');
|
|
$return_data = ['watermark' => $iswatermark];
|
|
if ($iswatermark) {
|
|
$wmconfig = [
|
|
'watermark' => $iswatermark,
|
|
'mark_type' => Config::get('mark_type'),
|
|
'mark_image' => Config::get('mark_image'),
|
|
'mark_width_height' => Config::get('mark_width_height'),
|
|
'mark_text' => Config::get('mark_text'),
|
|
'mark_text_color' => Config::get('mark_text_color'),
|
|
'mark_degree' => Config::get('mark_degree'),
|
|
'mark_quality' => Config::get('mark_quality'),
|
|
'mark_position' => Config::get('mark_position'),
|
|
];
|
|
$imgresource = '.' . $return_url;
|
|
$image = Image::open($imgresource);
|
|
//$image->open($imgresource);
|
|
$return_data['mark_type'] = $wmconfig['mark_type'];
|
|
if ($image->width() > $wmconfig['mark_width_height']['width'] && $image->height() > $wmconfig['mark_width_height']['height']) {
|
|
$save_filename = $this->basePath . '/original_image' . substr($return_url, 8); //截取 /uploads 后的内容
|
|
if (!is_dir(dirname($save_filename))) {
|
|
mkdir(dirname($save_filename), 0777, true);
|
|
}
|
|
$image->save($save_filename, null, 100);
|
|
if ($wmconfig['mark_type'] == 'text') {
|
|
//$image->text($wmconfig['mark_text'],'./hgzb.ttf',20,'#000000',9)->save($imgresource);
|
|
$ttf = './hgzb.ttf';
|
|
if (file_exists($ttf)) {
|
|
$size = $wmconfig['mark_text_size'] ? $wmconfig['mark_text_size'] : 30;
|
|
$color = $wmconfig['mark_text_color'] ? : '#000000';
|
|
if (!preg_match('/^#[0-9a-fA-F]{6}$/', $color)) {
|
|
$color = '#000000';
|
|
}
|
|
$transparency = intval((100 - $wmconfig['mark_degree']) * (127 / 100));
|
|
$color .= dechex($transparency);
|
|
$image->open($imgresource)->text($wmconfig['mark_text'], $ttf, $size, $color, $wmconfig['mark_position'])->save($imgresource);
|
|
$return_data['mark_text'] = $wmconfig['mark_text'];
|
|
}
|
|
} else {
|
|
//$image->water('.'.$wmconfig['mark_img'],9,$wmconfig['mark_degree'])->save($imgresource);
|
|
$waterPath = '.' . $wmconfig['mark_image'];
|
|
$quality = $wmconfig['mark_quality'] ? $wmconfig['mark_quality'] : 80;
|
|
$waterTempPath = dirname($waterPath) . '/temp_' . basename($waterPath);
|
|
$image->open($waterPath)->save($waterTempPath, null, $quality);
|
|
$image->open($imgresource)->water($waterTempPath, $wmconfig['mark_position'], $wmconfig['mark_degree'])->save($imgresource);
|
|
@unlink($waterTempPath);
|
|
}
|
|
}
|
|
}
|
|
return $return_data;
|
|
}
|
|
|
|
/**
|
|
* 规则替换命名文件
|
|
* @param $path
|
|
* @return string
|
|
*/
|
|
private function getFullPath($path) {
|
|
//替换日期事件
|
|
$t = time();
|
|
$d = explode('-', date("Y-y-m-d-H-i-s"));
|
|
$format = $path;
|
|
$format = str_replace("{yyyy}", $d[0], $format);
|
|
$format = str_replace("{yy}", $d[1], $format);
|
|
$format = str_replace("{mm}", $d[2], $format);
|
|
$format = str_replace("{dd}", $d[3], $format);
|
|
$format = str_replace("{hh}", $d[4], $format);
|
|
$format = str_replace("{ii}", $d[5], $format);
|
|
$format = str_replace("{ss}", $d[6], $format);
|
|
$format = str_replace("{uid}", $this->user_id, $format);
|
|
|
|
return $format;
|
|
}
|
|
|
|
private function format_exts($exts) {
|
|
$data = array();
|
|
foreach ($exts as $key => $value) {
|
|
$data[] = ltrim($value, '.');
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
}
|