Java对接数据万象API实现视频查重、视频相似度校验处理

使用依赖

            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>4.5.13</version>
            </dependency>
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>5.8.1</version>
            </dependency>
            <dependency>
                <groupId>com.qcloud</groupId>
                <artifactId>cos_api</artifactId>
                <version>5.6.36</version>
            </dependency>

视频DNA校验签名

1、腾讯官方提供的签名工具类

package com.hongmeng.util.tencent;

import static com.qcloud.cos.auth.COSSignerConstants.LINE_SEPARATOR;
import static com.qcloud.cos.auth.COSSignerConstants.Q_AK;
import static com.qcloud.cos.auth.COSSignerConstants.Q_HEADER_LIST;
import static com.qcloud.cos.auth.COSSignerConstants.Q_KEY_TIME;
import static com.qcloud.cos.auth.COSSignerConstants.Q_SIGNATURE;
import static com.qcloud.cos.auth.COSSignerConstants.Q_SIGN_ALGORITHM_KEY;
import static com.qcloud.cos.auth.COSSignerConstants.Q_SIGN_ALGORITHM_VALUE;
import static com.qcloud.cos.auth.COSSignerConstants.Q_SIGN_TIME;
import static com.qcloud.cos.auth.COSSignerConstants.Q_URL_PARAM_LIST;

import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import com.qcloud.cos.Headers;
import com.qcloud.cos.auth.AnonymousCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.auth.COSSessionCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.http.CosHttpRequest;
import com.qcloud.cos.http.HttpMethodName;
import com.qcloud.cos.internal.CosServiceRequest;
import com.qcloud.cos.utils.UrlEncoderUtils;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.digest.HmacUtils;

/**
 * @author zym
 * date:  2023-10-18 15:44
 */
public class COSSigner {
    private static Set<String> needSignedHeaderSet = new HashSet<>();
    private Boolean isCIWorkflowRequest = false;
    // Time offset between local and server
    private int localTimeDelta = 0;
    static {
        needSignedHeaderSet.add("cache-control");
        needSignedHeaderSet.add("content-disposition");
        needSignedHeaderSet.add("content-encoding");
        needSignedHeaderSet.add("content-length");
        needSignedHeaderSet.add("content-md5");
        needSignedHeaderSet.add("content-type");
        needSignedHeaderSet.add("expect");
        needSignedHeaderSet.add("expires");
        needSignedHeaderSet.add("host");
        needSignedHeaderSet.add("if-match");
        needSignedHeaderSet.add("if-modified-since");
        needSignedHeaderSet.add("if-none-match");
        needSignedHeaderSet.add("if-unmodified-since");
        needSignedHeaderSet.add("origin");
        needSignedHeaderSet.add("range");
        needSignedHeaderSet.add("transfer-encoding");
    }

    private boolean isAnonymous(COSCredentials cred) {
        return cred instanceof AnonymousCOSCredentials;
    }

    public <X extends CosServiceRequest> void sign(CosHttpRequest<X> request, COSCredentials cred, Date expiredTime) {
        if (isAnonymous(cred)) {
            return;
        }

        String authoriationStr =
                buildAuthorizationStr(request.getHttpMethod(), request.getResourcePath(),
                        request.getHeaders(), request.getParameters(), cred, expiredTime, true);

        request.addHeader(Headers.COS_AUTHORIZATION, authoriationStr);
        if (cred instanceof COSSessionCredentials) {
            request.addHeader(Headers.SECURITY_TOKEN,
                    ((COSSessionCredentials) cred).getSessionToken());
        }
    }

    public String buildPostObjectSignature(String secretKey, String keyTime, String policy) {
        String signKey = HmacUtils.hmacSha1Hex(secretKey, keyTime);
        String stringToSign = DigestUtils.sha1Hex(policy);
        return HmacUtils.hmacSha1Hex(signKey, stringToSign);
    }

    public String buildAuthorizationStr(HttpMethodName methodName, String resouce_path,
                                        COSCredentials cred,
                                        Date expiredTime) {
        Date startTime = new Date();
        return buildAuthorizationStr(methodName, resouce_path, new HashMap<>(), new HashMap<>(),
                cred, startTime, expiredTime, true);
    }

    public String buildAuthorizationStr(HttpMethodName methodName, String resouce_path,
                                        Map<String, String> headerMap, Map<String, String> paramMap, COSCredentials cred,
                                        Date expiredTime) {
        Date startTime = new Date();
        return buildAuthorizationStr(methodName, resouce_path, headerMap, paramMap,
                cred, startTime, expiredTime,true);
    }

    public String buildAuthorizationStr(HttpMethodName methodName, String resouce_path,
                                        Map<String, String> headerMap, Map<String, String> paramMap, COSCredentials cred,
                                        Date expiredTime, Boolean signHost) {
        Date startTime = new Date();
        return buildAuthorizationStr(methodName, resouce_path, headerMap, paramMap,
                cred, startTime, expiredTime, signHost);
    }

    public String buildAuthorizationStr(HttpMethodName methodName, String resouce_path,
                                        Map<String, String> headerMap, Map<String, String> paramMap, COSCredentials cred,
                                        Date startTime, Date expiredTime, Boolean signHost) {
        if (isAnonymous(cred)) {
            return null;
        }
        //万象工作流接口会出现uri带问号的情况 例如 /workflow/xxxxxx?active 这种情况?后面的参数不参与鉴权
        if (isCIWorkflowRequest){
            resouce_path = resouce_path.split("\\?")[0];
        }

        Map<String, String> signHeaders = buildSignHeaders(headerMap, signHost);
        // 签名中的参数和http 头部 都要进行字符串排序
        //对请求中的参数和http头部进行处理:对key先urlencode再小写处理,对value进行urlencode处理;
        //生成 key 到 value 的映射 Map,根据key按照字典序排序
        TreeMap<String, String> encodedSortedSignHeaders = buildEncodeSortedMemberMap(signHeaders);
        TreeMap<String, String> encodedSortedParams = buildEncodeSortedMemberMap(paramMap);

        //生成keylist
        String qHeaderListStr = buildSignMemberStr(encodedSortedSignHeaders);
        String qUrlParamListStr = buildSignMemberStr(encodedSortedParams);

        String qKeyTimeStr, qSignTimeStr;
        qKeyTimeStr = qSignTimeStr = buildTimeStr(startTime, expiredTime);
        String signKey = HmacUtils.hmacSha1Hex(cred.getCOSSecretKey(), qKeyTimeStr);
        String formatMethod = methodName.toString().toLowerCase();
        String formatUri = resouce_path;
        String formatParameters = formatMapToStr(encodedSortedParams);
        String formatHeaders = formatMapToStr(encodedSortedSignHeaders);

        String formatStr = new StringBuilder().append(formatMethod).append(LINE_SEPARATOR)
                .append(formatUri).append(LINE_SEPARATOR).append(formatParameters)
                .append(LINE_SEPARATOR).append(formatHeaders).append(LINE_SEPARATOR).toString();
        String hashFormatStr = DigestUtils.sha1Hex(formatStr);
        String stringToSign = new StringBuilder().append(Q_SIGN_ALGORITHM_VALUE)
                .append(LINE_SEPARATOR).append(qSignTimeStr).append(LINE_SEPARATOR)
                .append(hashFormatStr).append(LINE_SEPARATOR).toString();
        String signature = HmacUtils.hmacSha1Hex(signKey, stringToSign);

        String authoriationStr = new StringBuilder().append(Q_SIGN_ALGORITHM_KEY).append("=")
                .append(Q_SIGN_ALGORITHM_VALUE).append("&").append(Q_AK).append("=")
                .append(cred.getCOSAccessKeyId()).append("&").append(Q_SIGN_TIME).append("=")
                .append(qSignTimeStr).append("&").append(Q_KEY_TIME).append("=").append(qKeyTimeStr)
                .append("&").append(Q_HEADER_LIST).append("=").append(qHeaderListStr).append("&")
                .append(Q_URL_PARAM_LIST).append("=").append(qUrlParamListStr).append("&")
                .append(Q_SIGNATURE).append("=").append(signature).toString();
        return authoriationStr;
    }

    public boolean needSignedHeader(String header) {
        return needSignedHeaderSet.contains(header) || header.startsWith("x-cos-");
    }

    private Map<String, String> buildSignHeaders(Map<String, String> originHeaders, Boolean signHost) {
        Boolean hasHost = false;
        Map<String, String> signHeaders = new HashMap<>();
        for (Entry<String, String> headerEntry : originHeaders.entrySet()) {
            String key = headerEntry.getKey().toLowerCase();

            if (key.equals("host")) {
                hasHost = true;
            }

            if(needSignedHeader(key)) {
                String value = headerEntry.getValue();
                signHeaders.put(key, value);
            }
        }

        if (!hasHost && signHost) {
            String msg = String.format("buildAuthorization missing header: host. %s", originHeaders);
            throw new CosClientException(msg);
        }

        return signHeaders;
    }

    private TreeMap<String, String> buildEncodeSortedMemberMap(Map<String, String> signElements){
        TreeMap<String, String> encodeSortedSignElements = new TreeMap<>();

        for (Entry<String, String> header : signElements.entrySet()) {
            if (header.getKey() == null) {
                continue;
            }
            String encodeLowerKey = UrlEncoderUtils.encode(header.getKey().trim()).toLowerCase();
            String value = "";
            if (header.getValue()!=null){
                value = header.getValue().trim();
            }
            String encodeValue = UrlEncoderUtils.encode(value);
            encodeSortedSignElements.put(encodeLowerKey, encodeValue);
        }
        return encodeSortedSignElements;
    }

    private String buildSignMemberStr(Map<String, String> signHeaders) {
        StringBuilder strBuilder = new StringBuilder();
        boolean seenOne = false;
        for (String key : signHeaders.keySet()) {
            if (!seenOne) {
                seenOne = true;
            } else {
                strBuilder.append(";");
            }
            strBuilder.append(key);
        }
        return strBuilder.toString();
    }

    private String formatMapToStr(Map<String, String> kVMap) {
        StringBuilder strBuilder = new StringBuilder();
        boolean seeOne = false;
        for (Entry<String, String> entry : kVMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            if (!seeOne) {
                seeOne = true;
            } else {
                strBuilder.append("&");
            }
            strBuilder.append(key).append("=").append(value);
        }
        return strBuilder.toString();
    }

    private String buildTimeStr(Date startTime, Date endTime) {
        StringBuilder strBuilder = new StringBuilder();
        long startTimestamp = startTime.getTime() / 1000 + localTimeDelta;
        long endTimestamp = endTime.getTime() / 1000 + localTimeDelta;
        strBuilder.append(startTimestamp).append(";").append(endTimestamp);
        return strBuilder.toString();
    }

    public static Set<String> getNeedSignedHeaderSet() {
        return needSignedHeaderSet;
    }

    public static void setNeedSignedHeaderSet(Set<String> needSignedHeaderSet) {
        COSSigner.needSignedHeaderSet = needSignedHeaderSet;
    }

    public void setCIWorkflowRequest(Boolean CIRequest) {
        isCIWorkflowRequest = CIRequest;
    }

    public int getLocalTimeDelta() {
        return localTimeDelta;
    }

    public void setLocalTimeDelta(int localTimeDelta) {
        this.localTimeDelta = localTimeDelta;
    }
}

2、基于腾讯云提供的官方签名方法,做一个适应于自己业务的方法封装

    /**
     * 获取一个临时签名
     * https://cloud.tencent.com/document/product/436/35217#.E7.94.9F.E6.88.90.E7.AD.BE.E5.90.8D
     *
     * @param methodName 请求的 HTTP 方法
     * @param path       需要访问的路径
     * @param params     本次请求参数
     * @param headers    填写本次请求的头部
     */
    public static String getSigner(HttpMethodName methodName, String path, Map<String, String> params, Map<String, String> headers) {
        // 这里需要已经获取到临时密钥的结果。
        JSONObject credentials = getSnapToken().getJSONObject("credentials");
        String sessionToken = credentials.getString("sessionToken");
        //腾讯云cos中bucket对应secretId与secretKey
        COSCredentials cred = new BasicSessionCredentials(secretId, secretKey, sessionToken);
        //若key不是以“/”开头,则需要在 key 的开头加上“/”,否则直接 resource_path=key
        String resourcePath = path.startsWith("/") ? path : "/" + path;
        // 用来生成签名
        COSSigner signer = new COSSigner();
        // 这里设置签名在半个小时后过期
        Date expirationDate = new Date(System.currentTimeMillis() + 30L * 60L * 1000L);
        //获取签名
        return signer.buildAuthorizationStr(methodName, resourcePath, headers, params, cred, expirationDate, true);
    }

视频DNA相关API

public class CosDNATest {
    private final String host = "https://ad-zym-test.ci.ap-guangzhou.myqcloud.com";
    //基于HttpClient依赖进行封装的工具类
    private final HttpClientUtil instance = HttpClientUtil.getInstance();

    /**
     * 提交一个视频DNA任务
     */
    @Test
    public void commitVideoDNA() {
        //存储在cos中的视频key
        String key = "2023-10-12/8d00c3344784276dd9b3e19447638c57.mp4";
        String reqStr = "<Request>" +
                "    <Tag>DNA</Tag>" +
                "    <Input>" +
                "        <Object>" + key + "</Object>" +
                "    </Input>" +
                "    <Operation>" +
                "        <DnaConfig>" +
                "            <RuleType>GetFingerPrint</RuleType>" +
                "            <DnaDbId>dev_238</DnaDbId>" +
                "        </DnaConfig>" +
                "        <UserData>zym</UserData>" +
                "        <JobLevel>0</JobLevel>" +
                "    </Operation>" +
                "    <CallBackType>Url</CallBackType>" +
                "    <CallBack>http://adtech.test.link.hmgreat.com:8089/dnaCallBack</CallBack>" +
                "    <CallBackFormat>JSON</CallBackFormat>" +
                "</Request>";
        Map<String, String> headers = new HashMap<>();
        headers.put("host", "ad-zym-test.ci.ap-guangzhou.myqcloud.com");
        //获取本次任务提交的签名
        String signer = TencentCosUtil.getSigner(HttpMethodName.POST, "/jobs", Collections.emptyMap(), headers);
        headers.put("Content-Type", "application/xml");
        headers.put("Authorization", signer);
        String xmlBody = instance.postHttpResponseXmlBody(host + "/jobs", headers, reqStr);
        //将XML转化为JSON
        JSONObject body = XML.toJSONObject(xmlBody);
        System.out.println("body = " + body);

    }

    /**
     * 获取视频DNA提交任务后的信息,如任务处理状态
     */
    @Test
    public void getVideoDNAJobInfo() {
        String tempUrl = host + "/jobs/j5894a76c6e2311eeb97b6d08ebe82b8f";
        Map<String, String> headers = new HashMap<>();
        headers.put("host", "ad-zym-test.ci.ap-guangzhou.myqcloud.com");
        String signer = TencentCosUtil.getSigner(HttpMethodName.GET, "/jobs/j5894a76c6e2311eeb97b6d08ebe82b8f", Collections.emptyMap(), headers);
        headers.put("Authorization", signer);
        String responseBody = instance.getHttpResponseBody(tempUrl, headers);
        System.out.println("responseBody = " + responseBody);
    }

    /**
     * 查询cos中对应bucket所关联的DNA库
     */
    @Test
    public void getDnaDBList() {
        String tempUrl = host + "/dnadb";
        Map<String, String> headers = new HashMap<>();
        headers.put("host", "ad-zym-test.ci.ap-guangzhou.myqcloud.com");
        String signer = TencentCosUtil.getSigner(HttpMethodName.GET, "/dnadb", Collections.emptyMap(), headers);
        headers.put("Authorization", signer);
        String responseBody = instance.getHttpResponseBody(tempUrl, headers);
        System.out.println("responseBody = " + responseBody);
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Acmen-zym

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值