228 lines
6.5 KiB
Go
228 lines
6.5 KiB
Go
package api
|
||
|
||
import (
|
||
"fmt"
|
||
"io"
|
||
"os"
|
||
"path/filepath"
|
||
"strings"
|
||
|
||
"contentSecurityDemo/conf"
|
||
"contentSecurityDemo/internal/model"
|
||
|
||
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
||
green20220302 "github.com/alibabacloud-go/green-20220302/v2/client"
|
||
util "github.com/alibabacloud-go/tea-utils/v2/service"
|
||
"github.com/alibabacloud-go/tea/tea"
|
||
)
|
||
|
||
// ImageScanner 图片内容安全扫描器2.0
|
||
type ImageScanner struct {
|
||
Client *green20220302.Client
|
||
Config *conf.Config
|
||
}
|
||
|
||
// ImageServiceType 图片审核服务类型
|
||
type ImageServiceType string
|
||
|
||
const (
|
||
// BaselineCheckGlobal 通用基线检测
|
||
BaselineCheckGlobal ImageServiceType = "baselineCheck_global"
|
||
// PostImageCheckByVLGlobal 大小模型融合图片审核服务(专业版)
|
||
PostImageCheckByVLGlobal ImageServiceType = "postImageCheckByVL_global"
|
||
// AigcDetectorGlobal AI生成图片鉴别
|
||
AigcDetectorGlobal ImageServiceType = "aigcDetector_global"
|
||
)
|
||
|
||
// NewImageScanner 创建图片扫描器
|
||
func NewImageScanner(config *conf.Config) (*ImageScanner, error) {
|
||
// 获取有效的访问凭证
|
||
accessKeyID, accessKeySecret, securityToken := config.GetEffectiveCredentials()
|
||
|
||
// 创建配置
|
||
clientConfig := &openapi.Config{
|
||
AccessKeyId: tea.String(accessKeyID),
|
||
AccessKeySecret: tea.String(accessKeySecret),
|
||
SecurityToken: tea.String(securityToken),
|
||
RegionId: tea.String(config.Region),
|
||
Endpoint: tea.String(config.Endpoint),
|
||
}
|
||
|
||
// 创建客户端
|
||
client, err := green20220302.NewClient(clientConfig)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("创建客户端失败: %v", err)
|
||
}
|
||
|
||
return &ImageScanner{
|
||
Client: client,
|
||
Config: config,
|
||
}, nil
|
||
}
|
||
|
||
// ScanImageByURL 通过URL扫描图片
|
||
func (s *ImageScanner) ScanImageByURL(imageURL string, dataID string, serviceType ImageServiceType) (*model.ImageScanResponse, error) {
|
||
// 创建运行时配置
|
||
runtime := &util.RuntimeOptions{}
|
||
runtime.ReadTimeout = tea.Int(10000)
|
||
runtime.ConnectTimeout = tea.Int(10000)
|
||
|
||
// 构建请求参数
|
||
imageScanRequest := &green20220302.ImageModerationRequest{
|
||
Service: tea.String(string(serviceType)),
|
||
ServiceParameters: tea.String(fmt.Sprintf(`{"imageUrl":"%s","dataId":"%s"}`, imageURL, dataID)),
|
||
}
|
||
|
||
// 调用API
|
||
response, err := s.Client.ImageModerationWithOptions(imageScanRequest, runtime)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("请求失败: %v", err)
|
||
}
|
||
|
||
// 转换响应格式
|
||
scanResponse := &model.ImageScanResponse{
|
||
Code: tea.Int32Value(response.Body.Code),
|
||
Message: tea.StringValue(response.Body.Msg),
|
||
Data: make([]model.ImageScanData, 0),
|
||
}
|
||
|
||
// 创建单个数据项
|
||
scanData := model.ImageScanData{
|
||
DataID: *response.Body.Data.DataId,
|
||
Code: tea.Int32Value(response.Body.Code),
|
||
Message: "success",
|
||
Results: make([]*green20220302.ImageModerationResponseBodyDataResult, 0),
|
||
}
|
||
|
||
// 如果有结果数据,进行转换
|
||
if response.Body.Data != nil {
|
||
data := response.Body.Data
|
||
scanData.Results = append(scanData.Results, data.Result...)
|
||
}
|
||
|
||
scanResponse.Data = append(scanResponse.Data, scanData)
|
||
|
||
return scanResponse, nil
|
||
}
|
||
|
||
// ScanImageByFile 通过文件扫描图片
|
||
func (s *ImageScanner) ScanImageByFile(filePath string, dataID string, serviceType ImageServiceType) (*model.ImageScanResponse, error) {
|
||
// 读取文件
|
||
file, err := os.Open(filePath)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("打开文件失败: %v", err)
|
||
}
|
||
defer file.Close()
|
||
|
||
// 检查文件大小(限制为9MB)
|
||
fileInfo, err := file.Stat()
|
||
if err != nil {
|
||
return nil, fmt.Errorf("获取文件信息失败: %v", err)
|
||
}
|
||
|
||
if fileInfo.Size() > 9*1024*1024 {
|
||
return nil, fmt.Errorf("文件大小超过9MB限制")
|
||
}
|
||
|
||
// 读取文件内容并转换为base64
|
||
fileContent, err := io.ReadAll(file)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("读取文件失败: %v", err)
|
||
}
|
||
|
||
// 检查文件类型 - 2.0版本支持更多格式
|
||
ext := strings.ToLower(filepath.Ext(filePath))
|
||
supportedExts := []string{".jpg", ".jpeg", ".png", ".bmp", ".gif", ".webp", ".tiff", ".svg", ".ico", ".heic"}
|
||
isSupported := false
|
||
for _, supportedExt := range supportedExts {
|
||
if ext == supportedExt {
|
||
isSupported = true
|
||
break
|
||
}
|
||
}
|
||
|
||
if !isSupported {
|
||
return nil, fmt.Errorf("不支持的文件格式: %s", ext)
|
||
}
|
||
|
||
// 将文件内容转换为base64
|
||
base64Content := fmt.Sprintf("data:image/%s;base64,%s", ext[1:],
|
||
strings.ReplaceAll(string(fileContent), "\n", ""))
|
||
|
||
// 创建运行时配置
|
||
runtime := &util.RuntimeOptions{}
|
||
runtime.ReadTimeout = tea.Int(10000)
|
||
runtime.ConnectTimeout = tea.Int(10000)
|
||
|
||
// 构建请求参数
|
||
imageScanRequest := &green20220302.ImageModerationRequest{
|
||
Service: tea.String(string(serviceType)),
|
||
ServiceParameters: tea.String(fmt.Sprintf(`{"content":"%s"}`, base64Content)),
|
||
}
|
||
|
||
// 调用API
|
||
response, err := s.Client.ImageModerationWithOptions(imageScanRequest, runtime)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("请求失败: %v", err)
|
||
}
|
||
|
||
// 转换响应格式
|
||
scanResponse := &model.ImageScanResponse{
|
||
Code: tea.Int32Value(response.Body.Code),
|
||
Message: tea.StringValue(response.Body.Msg),
|
||
Data: make([]model.ImageScanData, 0),
|
||
}
|
||
|
||
// 创建单个数据项
|
||
scanData := model.ImageScanData{
|
||
DataID: dataID,
|
||
Code: tea.Int32Value(response.Body.Code),
|
||
Results: make([]*green20220302.ImageModerationResponseBodyDataResult, 0),
|
||
}
|
||
if response.Body.Code == tea.Int32(200) {
|
||
scanData.Message = "success"
|
||
} else {
|
||
scanData.Message = tea.StringValue(response.Body.Msg)
|
||
}
|
||
|
||
// 如果有结果数据,进行转换
|
||
if response.Body.Data != nil {
|
||
// 这里需要根据实际的响应结构进行调整
|
||
// 暂时创建一个基本的结果结构
|
||
data := response.Body.Data
|
||
scanData.Results = append(scanData.Results, data.Result...)
|
||
}
|
||
|
||
scanResponse.Data = append(scanResponse.Data, scanData)
|
||
|
||
return scanResponse, nil
|
||
}
|
||
|
||
// PrintResult 打印扫描结果
|
||
func (s *ImageScanner) PrintResult(response *model.ImageScanResponse) {
|
||
fmt.Println("=== 图片内容安全审核结果===")
|
||
fmt.Printf("状态码: %d\n", response.Code)
|
||
fmt.Printf("消息: %s\n", response.Message)
|
||
|
||
for _, data := range response.Data {
|
||
fmt.Printf("\n数据ID: %s\n", data.DataID)
|
||
fmt.Printf("处理状态: %d - %s\n", data.Code, data.Message)
|
||
|
||
for _, result := range data.Results {
|
||
if result.Confidence != nil {
|
||
fmt.Printf("置信度: %f\n", *result.Confidence)
|
||
}
|
||
if result.Description != nil {
|
||
fmt.Printf("描述: %s\n", *result.Description)
|
||
}
|
||
if result.Label != nil {
|
||
fmt.Printf("标签: %s\n", *result.Label)
|
||
}
|
||
if result.RiskLevel != nil {
|
||
fmt.Printf("风险等级: %s\n", *result.RiskLevel)
|
||
}
|
||
fmt.Println("---")
|
||
}
|
||
}
|
||
}
|