本文目录导读:

我将为您介绍PHP图片审核的接入方案,主要涵盖常见的云服务商API对接和实现方案。
常见图片审核服务商
1 阿里云内容安全
<?php
class AliyunImageReview {
private $accessKeyId;
private $accessKeySecret;
public function __construct($accessKeyId, $accessKeySecret) {
$this->accessKeyId = $accessKeyId;
$this->accessKeySecret = $accessKeySecret;
}
/**
* 图片审核
* @param string $imageUrl 图片URL
* @return array 审核结果
*/
public function reviewImage($imageUrl) {
$host = "https://green.cn-shanghai.aliyuncs.com";
$path = "/green/image/scan";
$content = json_encode([
'tasks' => [
['dataId' => uniqid(), 'url' => $imageUrl]
],
'scenes' => ['porn', 'terrorism', 'politician']
], JSON_UNESCAPED_UNICODE);
// 生成签名
$time = time() * 1000;
$nonce = md5(uniqid());
// 使用阿里云SDK生成签名
$signature = $this->generateSignature($content, $time, $nonce);
$headers = [
'Authorization: ' . $signature,
'Content-Type: application/json',
'x-acs-signature-method: HMAC-SHA1',
'x-acs-signature-nonce: ' . $nonce,
'x-acs-signature-version: 1.0',
'x-acs-version: 2018-05-09',
'Date: ' . gmdate('D, d M Y H:i:s \G\M\T', time())
];
// 发送请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $host . $path);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $content);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
private function generateSignature($content, $time, $nonce) {
// 签名字符串构造
$stringToSign = $content . $time . $nonce;
$signature = base64_encode(
hash_hmac('sha1', $stringToSign, $this->accessKeySecret, true)
);
return "acs " . $this->accessKeyId . ":" . $signature;
}
}
2 腾讯云图片审核
<?php
class TencentImageReview {
private $secretId;
private $secretKey;
public function __construct($secretId, $secretKey) {
$this->secretId = $secretId;
$this->secretKey = $secretKey;
}
/**
* 图片审核
* @param string $imageUrl 图片URL
* @return array 审核结果
*/
public function reviewImage($imageUrl) {
// 使用腾讯云SDK
try {
$credential = new Credential($this->secretId, $this->secretKey);
$client = new ImageModerationClient($credential, "ap-guangzhou");
$req = new ImageModerationRequest();
$params = json_encode([
'ImageUrl' => $imageUrl,
'BizType' => ''
]);
$req->fromJsonString($params);
$resp = $client->ImageModeration($req);
return json_decode($resp->toJsonString(), true);
} catch (Exception $e) {
return ['error' => $e->getMessage()];
}
}
}
通用图片审核封装类
<?php
class ImageReviewService {
private $provider;
private $config;
public function __construct($provider = 'aliyun') {
$this->provider = $provider;
$this->config = $this->loadConfig();
}
private function loadConfig() {
return [
'aliyun' => [
'accessKeyId' => getenv('ALIYUN_ACCESS_KEY_ID'),
'accessKeySecret' => getenv('ALIYUN_ACCESS_KEY_SECRET'),
'region' => 'cn-shanghai'
],
'tencent' => [
'secretId' => getenv('TENCENT_SECRET_ID'),
'secretKey' => getenv('TENCENT_SECRET_KEY'),
'region' => 'ap-guangzhou'
]
];
}
/**
* 统一审核入口
* @param string $imageUrl
* @param string $type 审核类型:image/video
* @return array
*/
public function review($imageUrl, $type = 'image') {
try {
switch ($this->provider) {
case 'aliyun':
$result = $this->reviewWithAliyun($imageUrl);
break;
case 'tencent':
$result = $this->reviewWithTencent($imageUrl);
break;
default:
throw new Exception("不支持的审核服务商");
}
return $this->formatResult($result);
} catch (Exception $e) {
return [
'success' => false,
'error' => $e->getMessage(),
'suggestion' => 'block'
];
}
}
/**
* 统一结果格式
*/
private function formatResult($result) {
$default = [
'success' => false,
'suggestion' => 'pass', // pass, review, block
'labels' => [],
'score' => 0,
'raw' => $result
];
// 根据不同服务商解析结果
if ($this->provider == 'aliyun') {
return $this->parseAliyunResult($result, $default);
} elseif ($this->provider == 'tencent') {
return $this->parseTencentResult($result, $default);
}
return $default;
}
private function parseAliyunResult($result, $default) {
if (isset($result['data'][0]['results'][0])) {
$review = $result['data'][0]['results'][0];
$default['suggestion'] = $review['suggestion'];
$default['score'] = $review['rate'] ?? 0;
foreach ($review['details'] ?? [] as $detail) {
$default['labels'][] = [
'label' => $detail['label'],
'score' => $detail['rate'] ?? 0
];
}
$default['success'] = true;
}
return $default;
}
private function parseTencentResult($result, $default) {
if (isset($result['Data']['Suggestion'])) {
$default['suggestion'] = $result['Data']['Suggestion'];
if (isset($result['Data']['Label'])) {
$default['labels'][] = [
'label' => $result['Data']['Label'],
'score' => $result['Data']['Score'] ?? 0
];
}
$default['score'] = $result['Data']['Score'] ?? 0;
$default['success'] = true;
}
return $default;
}
private function reviewWithAliyun($imageUrl) {
// 阿里云审核实现
$aliyun = new AliyunImageReview(
$this->config['aliyun']['accessKeyId'],
$this->config['aliyun']['accessKeySecret']
);
return $aliyun->reviewImage($imageUrl);
}
private function reviewWithTencent($imageUrl) {
// 腾讯云审核实现
$tencent = new TencentImageReview(
$this->config['tencent']['secretId'],
$this->config['tencent']['secretKey']
);
return $tencent->reviewImage($imageUrl);
}
}
本地图片审核实现
<?php
class LocalImageReview {
/**
* 基于规则的本地图片审核
*/
public function reviewLocalImage($imagePath) {
$result = [
'success' => false,
'suggestion' => 'pass',
'reason' => ''
];
try {
// 1. 基础检查
if (!file_exists($imagePath)) {
throw new Exception("图片不存在");
}
// 2. 获取图片信息
$imageInfo = getimagesize($imagePath);
$width = $imageInfo[0];
$height = $imageInfo[1];
$mime = $imageInfo['mime'];
// 3. 检查图片大小
$fileSize = filesize($imagePath);
$maxSize = 10 * 1024 * 1024; // 10MB
if ($fileSize > $maxSize) {
$result['suggestion'] = 'block';
$result['reason'] = '图片过大';
return $result;
}
// 4. 检查图片格式
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
if (!in_array($mime, $allowedTypes)) {
$result['suggestion'] = 'block';
$result['reason'] = '不支持的图片格式';
return $result;
}
// 5. 基于GD库的简单检测
if (extension_loaded('gd')) {
$image = imagecreatefromstring(file_get_contents($imagePath));
// 检测肤色比例(简单的色情内容检测)
$skinRatio = $this->detectSkinRatio($image);
if ($skinRatio > 0.4) {
$result['suggestion'] = 'review';
$result['reason'] = '图片可能包含不当内容';
}
imagedestroy($image);
}
$result['success'] = true;
} catch (Exception $e) {
$result['success'] = false;
$result['reason'] = $e->getMessage();
}
return $result;
}
/**
* 简单的肤色检测(仅作示例)
*/
private function detectSkinRatio($image) {
$width = imagesx($image);
$height = imagesy($image);
$skinCount = 0;
$totalCount = 0;
for ($x = 0; $x < $width; $x += 5) {
for ($y = 0; $y < $height; $y += 5) {
$rgb = imagecolorat($image, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
// 简单的肤色判断逻辑
if ($r > 95 && $g > 40 && $b > 20 &&
$r > $g && $r > $b &&
$r - $gamax > 15 &&
$r - $b > 15) {
$skinCount++;
}
$totalCount++;
}
}
return $skinCount / max($totalCount, 1);
}
/**
* 批量审核图片
*/
public function batchReview($imagePaths) {
$results = [];
foreach ($imagePaths as $imagePath) {
$results[$imagePath] = $this->reviewLocalImage($imagePath);
}
return $results;
}
}
完整接入示例
<?php
// 接口调用示例
require_once 'ImageReviewService.php';
require_once 'LocalImageReview.php';
class ImageReviewController {
private $reviewService;
private $localReviewer;
public function __construct() {
// 使用阿里云服务
$this->reviewService = new ImageReviewService('aliyun');
$this->localReviewer = new LocalImageReview();
}
/**
* 上传并审核图片
*/
public function uploadAndReview() {
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
return $this->jsonResponse(false, '请求方法不正确');
}
if (!isset($_FILES['image'])) {
return $this->jsonResponse(false, '没有上传图片');
}
$file = $_FILES['image'];
// 1. 保存临时文件
$uploadDir = '/tmp/uploads/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
$tempFile = $uploadDir . uniqid() . '_' . $file['name'];
if (!move_uploaded_file($file['tmp_name'], $tempFile)) {
return $this->jsonResponse(false, '文件保存失败');
}
// 2. 本地基础审核
$localResult = $this->localReviewer->reviewLocalImage($tempFile);
if ($localResult['suggestion'] === 'block') {
return $this->jsonResponse(false, '图片审核未通过:' . $localResult['reason']);
}
// 3. 上传到对象存储或获取可访问URL
$imageUrl = $this->uploadToStorage($tempFile);
// 4. 云端专业审核
$cloudResult = $this->reviewService->review($imageUrl);
// 5. 处理审核结果
$response = [
'success' => true,
'data' => [
'imageUrl' => $imageUrl,
'reviewResult' => $cloudResult
]
];
if ($cloudResult['suggestion'] === 'block') {
$response['data']['status'] = 'blocked';
$response['data']['message'] = '图片包含违规内容';
} elseif ($cloudResult['suggestion'] === 'review') {
$response['data']['status'] = 'pending';
$response['data']['message'] = '图片需要人工审核';
} else {
$response['data']['status'] = 'approved';
$response['data']['message'] = '图片审核通过';
}
// 清理临时文件
unlink($tempFile);
return $this->jsonResponse(true, '审核完成', $response['data']);
}
/**
* 上传到对象存储(示例)
*/
private function uploadToStorage($filePath) {
// 这里实现你的对象存储上传逻辑
// OSS、COS、七牛云等
$ossUrl = 'https://your-bucket.oss-cn-shanghai.aliyuncs.com/' . basename($filePath);
// 简化示例,实际需要上传文件
return $ossUrl;
}
/**
* JSON响应
*/
private function jsonResponse($success, $message, $data = []) {
header('Content-Type: application/json');
echo json_encode([
'success' => $success,
'message' => $message,
'data' => $data
], JSON_UNESCAPED_UNICODE);
exit;
}
}
// 使用示例
$controller = new ImageReviewController();
$controller->uploadAndReview();
配置和优化建议
<?php
// 配置文件 config.php
return [
// 审核服务配置
'review' => [
'provider' => 'aliyun', // 服务商:aliyun/tencent
// 阿里云配置
'aliyun' => [
'accessKeyId' => 'your-access-key-id',
'accessKeySecret' => 'your-access-key-secret',
'region' => 'cn-shanghai',
'scenes' => ['porn', 'terrorism', 'politician', 'ad']
],
// 腾讯云配置
'tencent' => [
'secretId' => 'your-secret-id',
'secretKey' => 'your-secret-key',
'region' => 'ap-guangzhou'
],
// 审核策略
'strategy' => [
'allowPass' => true, // 是否允许通过
'allowReview' => true, // 是否需要人工审核
'maxBlockScore' => 80, // 拦截分数
'minPassScore' => 20 // 通过分数
]
],
// 图片上传配置
'upload' => [
'maxSize' => 10 * 1024 * 1024, // 10MB
'allowedTypes' => ['jpg', 'jpeg', 'png', 'gif', 'webp'],
'storage' => 'oss', // oss/cos/qiniu/local
'oss' => [
'bucket' => 'your-bucket',
'endpoint' => 'oss-cn-shanghai.aliyuncs.com'
]
]
];
注意事项
- 安全性:API密钥务必通过环境变量或配置文件管理,不要硬编码在代码中
- 缓存优化:对审核结果进行缓存,避免重复审核
- 异步处理:大批量图片审核建议使用队列异步处理
- 兜底方案:云服务异常时,确保有本地审核方案兜底
- 合规性:确保图片审核流程符合相关法律法规要求
方案可根据实际需求选择使用,建议结合本地预审和云服务精审,在保证效果的同时控制成本。