【黑马头条】内容安全增强版之图片审核

本文介绍了如何将黑马头条项目适配阿里云内容安全增强版接口,通过修改官方SDK以支持本地文件上传和重复使用连接,提高性能。涉及Pom依赖、工具类GreenImageScan的实现以及可优化点
摘要由CSDN通过智能技术生成

 因为黑马头条用的是阿里云的内容安全1.0接口,只有企业用户才能使用,所以我们只能改装他的审核工具类,使用阿里云的内容安全增强版的接口来实现图片审核。

为了能完全适配黑马头条项目的接口规范,我对官网提供的JAVA案例进行了改动,官网的SDK图片上传方式有三种:

  1. 使用公网url,这一点我们不符合,因为如果我们使用虚拟机的minio,那只能在局域网访问;
  2. 使用OSS云服务,开通云存储服务,将文件搬到阿里云上再审核,这样比较方便,但和黑马头条的技术栈不匹配。
  3. 本地上传(本质上还是临时上传到OSS上,再审核,不过不需要我们开通OSS服务,比较方便),但是上传方式和黑马头条不同,这里的SDK上传的传入值是文件在本地的路径,黑马是byteArray字节数组。

综合考量,改动方式3,在官网测试案例的基础上,将 fileStorageService 得到的字节数组转换为本地的文件,再将文件路径作为参数上传文件至阿里云,实现如下:

Pom依赖:

<!--安装内容检测SDK-->
<dependency>
  <groupId>com.aliyun</groupId>
  <artifactId>green20220302</artifactId>
  <version>2.1.0</version>
</dependency>

<!--安装OSS SDK-->
<dependency>
  <groupId>com.aliyun.oss</groupId>
  <artifactId>aliyun-sdk-oss</artifactId>
  <version>3.16.3</version>
</dependency>

GreenImageScan工具类: 

package com.heima.common.aliyun;

import com.alibaba.fastjson.JSON;
import com.aliyun.green20220302.Client;
import com.aliyun.green20220302.models.DescribeUploadTokenResponse;
import com.aliyun.green20220302.models.DescribeUploadTokenResponseBody;
import com.aliyun.green20220302.models.ImageModerationRequest;
import com.aliyun.green20220302.models.ImageModerationResponse;
import com.aliyun.green20220302.models.ImageModerationResponseBody;
import com.aliyun.green20220302.models.ImageModerationResponseBody.ImageModerationResponseBodyData;
import com.aliyun.green20220302.models.ImageModerationResponseBody.ImageModerationResponseBodyDataResult;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import io.minio.ObjectStat;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "aliyun")
public class GreenImageScan {

    private String accessKeyId;
    private String secret;
    private String imageService;
    private String endpoint;

    //服务是否部署在vpc上
    public boolean isVPC = false;

    //文件上传token endpoint->token
    public Map<String, DescribeUploadTokenResponseBody.DescribeUploadTokenResponseBodyData> tokenMap = new HashMap<>();

    //上传文件请求客户端 
    public OSS ossClient = null;

    /**
     * 创建请求客户端
     *
     * @param accessKeyId
     * @param secret
     * @param endpoint
     * @return
     * @throws Exception
     */
    public Client createClient(String accessKeyId, String secret, String endpoint) throws Exception {
        Config config = new Config();
        config.setAccessKeyId(accessKeyId);
        config.setAccessKeySecret(secret);
        // 设置http代理。
        // config.setHttpProxy("http://10.10.xx.xx:xxxx");
        // 设置https代理。
        // config.setHttpsProxy("https://10.10.xx.xx:xxxx");
        // 接入区域和地址请根据实际情况修改
        config.setEndpoint(endpoint);
        return new Client(config);
    }

    /**
     * 创建上传文件请求客户端
     *
     * @param tokenData
     * @param isVPC
     */
    public void getOssClient(DescribeUploadTokenResponseBody.DescribeUploadTokenResponseBodyData tokenData, boolean isVPC) {
        //注意,此处实例化的client请尽可能重复使用,避免重复建立连接,提升检测性能。
        if (isVPC) {
            ossClient = new OSSClientBuilder().build(tokenData.ossInternalEndPoint, tokenData.getAccessKeyId(), tokenData.getAccessKeySecret(), tokenData.getSecurityToken());
        } else {
            ossClient = new OSSClientBuilder().build(tokenData.ossInternetEndPoint, tokenData.getAccessKeyId(), tokenData.getAccessKeySecret(), tokenData.getSecurityToken());
        }
    }

    /**
     * 上传文件
     *
     * @param filePath
     * @param tokenData
     * @return
     * @throws Exception
     */
    public String uploadFile(String filePath, DescribeUploadTokenResponseBody.DescribeUploadTokenResponseBodyData tokenData) throws Exception {
        String[] split = filePath.split("\\.");
        String objectName;
        if (split.length > 1) {
            objectName = tokenData.getFileNamePrefix() + UUID.randomUUID() + "." + split[split.length - 1];
        } else {
            objectName = tokenData.getFileNamePrefix() + UUID.randomUUID();
        }
        PutObjectRequest putObjectRequest = new PutObjectRequest(tokenData.getBucketName(), objectName, new File(filePath));
        ossClient.putObject(putObjectRequest);
        return objectName;
    }

    public ImageModerationResponse invokeFunction(String filePath) throws Exception {
        //注意,此处实例化的client请尽可能重复使用,避免重复建立连接,提升检测性能。
        Client client = createClient(accessKeyId, secret, endpoint);
        RuntimeOptions runtime = new RuntimeOptions();

        //本地文件的完整路径,例如D:\localPath\exampleFile.png。
        /*        String filePath = "D:\\localPath\\exampleFile.png";*/
        String bucketName = null;
        DescribeUploadTokenResponseBody.DescribeUploadTokenResponseBodyData uploadToken = tokenMap.get(endpoint);
        //获取文件上传token
        if (uploadToken == null || uploadToken.expiration <= System.currentTimeMillis() / 1000) {
            DescribeUploadTokenResponse tokenResponse = client.describeUploadToken();
            uploadToken = tokenResponse.getBody().getData();
            bucketName = uploadToken.getBucketName();
        }
        //上传文件请求客户端
        getOssClient(uploadToken, isVPC);

        //上传文件
        String objectName = uploadFile(filePath, uploadToken);

        // 检测参数构造。
        Map<String, String> serviceParameters = new HashMap<>();
        //文件上传信息
        serviceParameters.put("ossBucketName", bucketName);
        serviceParameters.put("ossObjectName", objectName);
        serviceParameters.put("dataId", UUID.randomUUID().toString());

        ImageModerationRequest request = new ImageModerationRequest();
        // 图片检测service:内容安全控制台图片增强版规则配置的serviceCode,示例:baselineCheck
        // 支持service请参考:https://help.aliyun.com/document_detail/467826.html?0#p-23b-o19-gff
        request.setService(imageService);
        request.setServiceParameters(JSON.toJSONString(serviceParameters));

        ImageModerationResponse response = null;
        try {
            response = client.imageModerationWithOptions(request, runtime);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return response;
    }

   

    public Map greeImageScan(byte[] bytes) throws Exception {
        /**
         * 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
         * 常见获取环境变量方式:
         * 方式一:
         *     获取RAM用户AccessKey ID:System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
         *     获取RAM用户AccessKey Secret:System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
         * 方式二:
         *     获取RAM用户AccessKey ID:System.getProperty("ALIBABA_CLOUD_ACCESS_KEY_ID");
         *     获取RAM用户AccessKey Secret:System.getProperty("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
         */
        // 接入区域和地址请根据实际情况修改。

        //首先将传入的byte数组抓换为imageCache文件,再将文件路径作为参数进行文件上传
        String imagePath = "imageCache";
        File file = new File(imagePath);
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        fileOutputStream.write(bytes);

        ImageModerationResponse response = invokeFunction(imagePath);
        Map<String, String> resultMap = new HashMap<>();
        try {
            // 自动路由。
            if (response != null) {
                //区域切换到cn-beijing。
                if (500 == response.getStatusCode() || (response.getBody() != null && 500 == (response.getBody().getCode()))) {
                    // 接入区域和地址请根据实际情况修改。
                    response = invokeFunction(imagePath);
                }
            }
            // 打印检测结果。
            if (response != null) {
                if (response.getStatusCode() == 200) {
                    ImageModerationResponseBody body = response.getBody();
                    System.out.println("requestId=" + body.getRequestId());
                    System.out.println("code=" + body.getCode());
                    System.out.println("msg=" + body.getMsg());
                    if (body.getCode() == 200) {
                        ImageModerationResponseBodyData data = body.getData();
                        System.out.println("dataId=" + data.getDataId());
                        List<ImageModerationResponseBodyDataResult> results = data.getResult();
                        if (results.get(0).getLabel().equals("nonLabel") || results.get(0).getLabel().equals("nonLabel_lib")) {
                            resultMap.put("suggestion", "pass");
                        } else {
                            StringBuilder stringBuilder = new StringBuilder();
                            for (ImageModerationResponseBodyDataResult result : results) {
                                System.out.println("label=" + result.getLabel());
                                System.out.println("confidence=" + result.getConfidence());
                                stringBuilder.append("[label:" + result.getLabel() + ",confidence=" + result.getConfidence() + "] ");
                                resultMap.put("suggestion", "block");
                                resultMap.put("result", stringBuilder.toString());
                            }
                        }
                    } else {
                        System.out.println("image moderation not success. code:" + body.getCode());
                    }
                } else {
                    System.out.println("response not success. status:" + response.getStatusCode());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            fileOutputStream.close();
            file.delete();
        }
        return resultMap;
    }
}

 其中的accessKeyId,secret,imageService,endpoint均需要我们在yaml文件中配置或者在nacos配置中心中配置。

imageService指的是图片检测增强版支持的检测服务。有以下几种:

  • baselineCheck:通用基线检测

  • baselineCheck_pro:通用基线检测_专业版

  • baselineCheck_cb:通用基线检测_海外版

  • tonalityImprove:内容治理检测

  • aigcCheck:AIGC图片风险检测

  • aigcCheck_cb:AIGC图片风险检测_出海版

  • profilePhotoCheck:头像图片检测

  • advertisingCheck:营销素材检测

  • liveStreamCheck:视频\直播截图检测

endpoint值得是支持的地域及接入地址,如下所示,根据自己的地区选择

 详细可见:如何使用图片审核增强版API_内容安全(Content Moderation)-阿里云帮助中心 (aliyun.com)

一些可以优化的地方:

因为本人比较菜,这个工具类还有很多地方需要优化,也欢迎评论区分享大家的代码。
以下是我个人认为可以优化的几个地方:

  1. 这个图片上传的连接最好可以重复使用,而不是上传一次就断开。
  2. 黑马头条提供的api的传入值类型是List<byte[]>,可以一次性处理多张图片,而我这个只能一次性处理一张,而且每处理一张就要重新建立连接,浪费资源和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值