diff --git a/README.md b/README.md index 68ebd93..b10da94 100755 --- a/README.md +++ b/README.md @@ -102,10 +102,12 @@ $HTTP["url"] =~ "^/(i|public)/" { * 2022-1-28 v2.4.8 dev - 修复无可疑图片时显示错误 +- 修复转换为webp时会复制一份bug - 修复开启登录上传后无法上传的bug - 增加安装时检测.user.ini - 增加检测鉴黄接口是否可以正确访问 - 将插件检测等敏感信息转义到管理目录 +- 增加异步处理文件,上传完毕后处理速度变快了 - 增加 [nsfwjs](https://github.com/infinitered/nsfwjs) 接口方式检测违规图片 - 作者测试时用的`docker`搭建 `docker`地址:[zengdawei/nsfw_restful_api ](https://hub.docker.com/r/zengdawei/nsfw_restful_api) diff --git a/api/index.php b/api/index.php index 2732dad..16e73f3 100755 --- a/api/index.php +++ b/api/index.php @@ -2,7 +2,6 @@ require_once __DIR__ . '/../application/function.php'; require_once APP_ROOT . '/api/function_API.php'; require_once APP_ROOT . '/application/class.upload.php'; -require_once APP_ROOT . '/application/WaterMask.php'; require_once APP_ROOT . '/config/api_key.php'; header('Access-Control-Allow-Origin:*'); @@ -43,54 +42,9 @@ if ($handle->uploaded) { // 转换图片为指定格式 $handle->image_convert = $config['imgConvert']; - /* 等比例缩减图片 放到前端了 - if ($config['imgRatio']) { - $handle->image_resize = true; - $handle->image_x = $config['image_x']; - $handle->image_y = $config['image_y']; - } - */ // 存储图片路径:images/201807/ $handle->process('../' . config_path()); - // 设置水印 - if ($config['watermark'] > 0) { - switch ($config['watermark']) { - case 1: // 文字水印 过滤gif - if (isAnimatedGif($handle->file_src_pathname) === 0) { - $arr = [ - # 水印图片路径(如果不存在将会被当成是字符串水印) - 'res' => $config['waterText'], - # 水印显示位置 - 'pos' => $config['waterPosition'], - # 不指定name(会覆盖原图,也就是保存成thumb.jpeg) - 'name' => $handle->file_dst_pathname, - 'font' => $config['textFont'], - 'fontSize' => $config['textSize'], - 'color' => $config['textColor'], - ]; - Imgs::setWater($handle->file_dst_pathname, $arr); - } - break; - case 2: // 图片水印 - if (isAnimatedGif($handle->file_src_pathname) === 0) { - $arr = [ - # 水印图片路径(如果不存在将会被当成是字符串水印) - 'res' => $config['waterImg'], - # 水印显示位置 - 'pos' => $config['waterPosition'], - # 不指定name(会覆盖原图,也就是保存成thumb.jpeg) - 'name' => $handle->file_dst_pathname, - ]; - Imgs::setWater($handle->file_dst_pathname, $arr); - } - break; - default: - echo $handle->error; - break; - } - } - // 图片完整相对路径:/i/2021/05/03/k88e7p.jpg if ($handle->processed) { header('Content-type:text/json'); @@ -129,14 +83,28 @@ if ($handle->uploaded) { exit(json_encode($reJson, JSON_UNESCAPED_UNICODE)); } - // 后续处理 - require_once APP_ROOT . '/application/process.php'; - // 日志 - if ($config['upload_logs']) { - @write_log(config_path() . $handle->file_dst_name, $handle->file_src_name, $handle->file_dst_pathname, $handle->file_src_size); - } - // 压缩|鉴黄 - process(config_path() . $handle->file_dst_name, $handle->file_dst_pathname); + /** 后续处理 */ + require APP_ROOT . '/application/process.php'; + + // 普通模式鉴黄 + process_checkImg($imageUrl); + // 使用fastcgi_finish_request操作 + if (function_exists('fastcgi_finish_request')) { + fastcgi_finish_request(); + // 日志 + if ($config['upload_logs']) @write_log(config_path() . $handle->file_dst_name, $handle->file_src_name, $handle->file_dst_pathname, $handle->file_src_size); + // 水印 + @water($handle->file_dst_pathname); + // 压缩 + @compress($handle->file_dst_pathname); + } else { + // 日志 + if ($config['upload_logs']) write_log(config_path() . $handle->file_dst_name, $handle->file_src_name, $handle->file_dst_pathname, $handle->file_src_size); + // 水印 + @water($handle->file_dst_pathname); + // 压缩 + @compress($handle->file_dst_pathname); + } unset($handle); } diff --git a/application/FsockService.php b/application/FsockService.php new file mode 100755 index 0000000..fbb4a69 --- /dev/null +++ b/application/FsockService.php @@ -0,0 +1,102 @@ + $value) { + if (is_array($value)) { + $date[$key] = serialize($value); + } else { + $date[$key] = $value; + } + } + } + + if ($method == "GET") { + $query = $date ? http_build_query($date) : ''; + $path .= "?" . $query; + } else { + $query = json_encode($date); + } + + //http消息头 + $out = $method . " " . $path . " HTTP/1.1\r\n"; + $out .= "HOST: " . $host . "\r\n"; + if ($method == "POST") { + $out .= "Content-Length:" . strlen($query) . "\r\n"; + } + $out .= "Accept: application/json, text/plain, */*\r\n"; + $out .= "Access-Control-Allow-Credentials: true\r\n"; + $out .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $out .= "Connection: Close\r\n\r\n"; + if ($method == "POST") { + $out .= $query; + } + + fputs($fp, $out); + usleep(20000); + //忽略执行结果 + /*while (!feof($fp)) { + echo fgets($fp, 128); + }*/ + fclose($fp); + + return true; +} +/* +$p = array( + 'test'=>1222, + 'test1'=>2222, + ); +var_dump(request_asynchronous('/test.php', 'GET', $p, 'https://png.cm')); +*/ \ No newline at end of file diff --git a/application/compress/Imagick/class.Imgcompress.php b/application/compress/Imagick/class.Imgcompress.php index 352b350..dabb017 100755 --- a/application/compress/Imagick/class.Imgcompress.php +++ b/application/compress/Imagick/class.Imgcompress.php @@ -95,7 +95,7 @@ class Imgcompress private function _saveImage($dstImgName) { if (empty($dstImgName)) return false; - $allowImgs = array('.jpg', '.jpeg', '.png', '.bmp', '.wbmp', '.gif','webp'); //如果目标图片名有后缀就用目标图片扩展名 后缀,如果没有,则用源图的扩展名 + $allowImgs = array('.jpg', '.jpeg', '.png', '.bmp', '.wbmp', '.gif','.webp'); // 如果目标图片名有后缀就用目标图片扩展名 后缀,如果没有,则用源图的扩展名 $dstExt = strrchr($dstImgName, "."); $sourseExt = strrchr($this->src, "."); if (!empty($dstExt)) $dstExt = strtolower($dstExt); diff --git a/application/function.php b/application/function.php index 00c8e47..b976165 100755 --- a/application/function.php +++ b/application/function.php @@ -604,6 +604,7 @@ function moderatecontent_json($img, $url = null) curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArray); + curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'); $output = curl_exec($ch); curl_close($ch); @@ -716,14 +717,12 @@ function checkImg($imageUrl, $type = 1) $old_path = APP_ROOT . str_replace($config['imgurl'], '', $imageUrl); // 提交网址中的文件路径 /i/2021/10/29/p8vypd.png $name = date('Y_m_d') . '_' . basename($imageUrl); // 文件名 2021_10_30_p8vypd.png $new_path = APP_ROOT . $config['path'] . 'suspic/' . $name; // 新路径含文件名 - $cache_dir = APP_ROOT . $config['path'] . 'suspic/'; // suspic路径 + $suspic_dir = APP_ROOT . $config['path'] . 'suspic/'; // suspic路径 - if (is_dir($cache_dir)) { // 创建suspic目录并移动 - rename($old_path, $new_path); - } else { - mkdir($cache_dir, 0777, true); - rename($old_path, $new_path); + if (!is_dir($suspic_dir)) { // 创建suspic目录并移动 + mkdir($suspic_dir, 0777, true); } + rename($old_path, $new_path); } } diff --git a/application/process.php b/application/process.php index 8392589..5c0a929 100755 --- a/application/process.php +++ b/application/process.php @@ -1,9 +1,10 @@ $config['waterText'], + # 水印显示位置 + 'pos' => $config['waterPosition'], + # 不指定name(会覆盖原图,也就是保存成thumb.jpeg) + 'name' => $source, + 'font' => APP_ROOT . $config['textFont'], + 'fontSize' => $config['textSize'], + 'color' => $config['textColor'], + ]; + Imgs::setWater($source, $arr); + } + } + + // 图片水印 + if ($config['watermark'] == 2) { + // 过滤gif + if (isAnimatedGif($source) === 0) { + $arr = [ + # 水印图片路径(如果不存在将会被当成是字符串水印) + 'res' => APP_ROOT . $config['waterImg'], + # 水印显示位置 + 'pos' => $config['waterPosition'], + # 不指定name(会覆盖原图,也就是保存成thumb.jpeg) + 'name' => $source, + ]; + Imgs::setWater($source, $arr); + } + } +} + +function process_checkImg($imgurl) +{ + global $config; // 图片违规检查 if ($config['checkImg'] == 1) { - @checkImg($config['imgurl'] . $filePath, 1); + checkImg($imgurl, 1); } if ($config['checkImg'] == 2) { - @checkImg($config['imgurl'] . $filePath, 2); + checkImg($imgurl, 2); } } @@ -82,3 +128,12 @@ function write_log($filePath, $sourceName, $absolutePath, $fileSize, $from = "We cache_write($logFileName, $log, 'logs'); */ } + +if (isset($_GET['auth'])) { + $checkAuth = md5($config['domain'] . $config['password']); + + // 鉴权 + if ($_GET['auth'] == $checkAuth) { + process_checkImg($_GET['img']); + } +} diff --git a/file.php b/application/upload.php similarity index 56% rename from file.php rename to application/upload.php index a024d0a..a5a3356 100755 --- a/file.php +++ b/application/upload.php @@ -1,8 +1,7 @@ uploaded) { // 存储图片路径:images/201807/ $handle->process(APP_ROOT . config_path()); - // 设置水印 - if ($config['watermark'] > 0) { - switch ($config['watermark']) { - case 1: // 文字水印 过滤gif - if (isAnimatedGif($handle->file_src_pathname) === 0) { - $arr = [ - # 水印图片路径(如果不存在将会被当成是字符串水印) - 'res' => $config['waterText'], - # 水印显示位置 - 'pos' => $config['waterPosition'], - # 不指定name(会覆盖原图,也就是保存成thumb.jpeg) - 'name' => $handle->file_dst_pathname, - 'font' => APP_ROOT . $config['textFont'], - 'fontSize' => $config['textSize'], - 'color' => $config['textColor'], - ]; - Imgs::setWater($handle->file_dst_pathname, $arr); - } - break; - case 2: // 图片水印 - if (isAnimatedGif($handle->file_src_pathname) === 0) { - $arr = [ - # 水印图片路径(如果不存在将会被当成是字符串水印) - 'res' => APP_ROOT . $config['waterImg'], - # 水印显示位置 - 'pos' => $config['waterPosition'], - # 不指定name(会覆盖原图,也就是保存成thumb.jpeg) - 'name' => $handle->file_dst_pathname, - ]; - Imgs::setWater($handle->file_dst_pathname, $arr); - } - break; - default: - echo $handle->error; - break; - } - } - /* // 创建缩略图 开启后会个别返回文件失败,暂时没找到替代方案,如果启用此项目,需要将list.php中的get_online_thumbnail改成return_thumbnail_images函数 if ($config['thumbnail']) { @@ -132,17 +93,46 @@ if ($handle->uploaded) { ); unset($handle); header('Content-Type:application/json; charset=utf-8'); + unset($handle); exit(json_encode($reJson, JSON_UNESCAPED_UNICODE)); } - // 后续处理 - require_once APP_ROOT . '/application/process.php'; - // 日志 - if ($config['upload_logs']) { - @write_log(config_path() . $handle->file_dst_name, $handle->file_src_name, $handle->file_dst_pathname, $handle->file_src_size); + + /** 后续处理 */ + require __DIR__ . '/process.php'; + /* + require __DIR__ . '/FsockService.php'; + + // 使用fosksock异步申请鉴黄 + if ($config['checkImg']) { + $process = array( + 'auth' => md5($config['domain'] . $config['password']), + 'img' => $imageUrl + ); + @request_asynchronous('/application/process.php', 'GET', $process, $config['domain']); } - // 压缩|鉴黄 - process(config_path() . $handle->file_dst_name, $handle->file_dst_pathname); + */ + // 普通模式鉴黄 + process_checkImg($imageUrl); + + // 使用fastcgi_finish_request操作 + if (function_exists('fastcgi_finish_request')) { + fastcgi_finish_request(); + // 日志 + if ($config['upload_logs']) @write_log(config_path() . $handle->file_dst_name, $handle->file_src_name, $handle->file_dst_pathname, $handle->file_src_size); + // 水印 + @water($handle->file_dst_pathname); + // 压缩 + @compress($handle->file_dst_pathname); + } else { + // 日志 + if ($config['upload_logs']) write_log(config_path() . $handle->file_dst_name, $handle->file_src_name, $handle->file_dst_pathname, $handle->file_src_size); + // 水印 + @water($handle->file_dst_pathname); + // 压缩 + @compress($handle->file_dst_pathname); + } + unset($handle); } diff --git a/config/config.php b/config/config.php index 859f7c0..5348975 100755 --- a/config/config.php +++ b/config/config.php @@ -17,11 +17,11 @@ $config=Array 'imgName'=>'default', 'maxSize'=>10485760, 'maxUploadFiles'=>30, - 'watermark'=>0, + 'watermark'=>2, 'waterText'=>'简单图床 - ww.png.cm', 'waterPosition'=>0, 'textColor'=>'255,0,0,1', - 'textSize'=>16, + 'textSize'=>20, 'textFont'=>'/public/static/hkxzy.ttf', 'waterImg'=>'/public/images/watermark.png', 'extensions'=>'gif,jpeg,png,tif,bmp,tif,svg,webp,jpg,tga,svg,ico', @@ -81,5 +81,5 @@ var _hmt = _hmt || []; 'check_ip_model'=>0, 'check_ip_list'=>'', 'version'=>'2.4.8', - 'form'=>'2022-02-02 03:25:00' + 'form'=>'2022-02-04 20:04:52' ); \ No newline at end of file diff --git a/index.php b/index.php index 7c17db9..9dca107 100755 --- a/index.php +++ b/index.php @@ -90,7 +90,7 @@ mustLogin(); // 自动上传 autoUpload: false, // 文件上传提交地址 - url: 'file.php', + url: '/application/upload.php', // 最大支持的上传文件 max_file_size: , // 分片上传 0为不分片 分片容易使图片上传失败