Help Center/ Video On Demand/ SDK Reference/ SDK Development Description
Updated on 2023-04-04 GMT+08:00

SDK Development Description

The SDK V3 encapsulates all APIs provided by VOD. You can use the VOD API Explorer to debug the APIs. Demos in different programming languages are generated for your reference.

If you have any questions or suggestions when using SDK V3, submit a service ticket to give feedback.

Uploading Media Files

When you need to use the server SDK to upload local media files, perform operations by referring to application example 1 or application example 2 in VOD API Reference. For details about how to upload a media file and confirm file upload in the application example, see Uploading Media Files to VOD and Verifying the Upload in the SDK. You can use HTTP PUT to upload a media file to the corresponding URL.

Generating a Signed URL

When using the SDK, you can use the URL validation algorithm on the VOD console or refer to the following demo to generate a signed URL.

package AuthUrlDemo;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

class AuthUrlDemo {
    // url is the original playback URL that is not encrypted. key is the key value configured on the VOD console.
    // Encryption algorithm A
    public static String createAuthInfoUrlByAlgorithmA(String url, String key) {
        try {
            checkParam(url, key);

            long timestamp = Instant.now().getEpochSecond();
            String randUid = UUID.randomUUID().toString().replaceAll("-", "");
            String uid = "0";
            String tmpRandKey = timestamp + "-" + randUid + "-" + uid;

            URL originUrl = new URL(url);
            String string2Md5 = originUrl.getPath() + "-" + tmpRandKey + "-" + key;
            String md5Hash = DigestUtils.md5Hex(string2Md5.getBytes(StandardCharsets.UTF_8));
            String authInfo = "auth_key=" + tmpRandKey + "-" + md5Hash;

            return StringUtils.isEmpty(originUrl.getQuery()) ? url + "?" + authInfo : url + "&" + authInfo;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    // Encryption algorithm B
    public static String createAuthInfoUrlByAlgorithmB(String url, String key) {
        try {
            checkParam(url, key);

            URL originUrl = new URL(url);
            String filePath = originUrl.getPath();
            String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm"));
            String str2Md5 = key + dateStr + filePath;
            String md5sum = DigestUtils.md5Hex(str2Md5.getBytes(StandardCharsets.UTF_8));

            return originUrl.getProtocol() + "://" + originUrl.getHost() + "/"
                    + dateStr + "/" + md5sum + originUrl.getFile();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    // Encryption algorithm C
    public static String createAuthInfoUrlByAlgorithmC(String url, String key) {
        try {
            checkParam(url, key);

            URL originUrl = new URL(url);
            String filePath = originUrl.getPath();
            String hexTime = Long.toHexString(Instant.now().getEpochSecond()).toUpperCase(Locale.ENGLISH);
            String str2Md5 = key + filePath + hexTime;
            String md5Hash = DigestUtils.md5Hex(str2Md5.getBytes(StandardCharsets.UTF_8));

            return originUrl.getProtocol() + "://" + originUrl.getHost() + "/" + md5Hash + "/" + hexTime + originUrl.getFile();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    // Encryption algorithm D
    public static String createAuthInfoUrlByAlgorithmD(String url, String key) {
        try {
            checkParam(url, key);

            URL originUrl = new URL(url);
            String urlPath = originUrl.getPath();
            String pathInUrl = urlPath.substring(0, urlPath.lastIndexOf("/") + 1);
            String data = encodeUrl(pathInUrl) + "$" + getUtcTime("yyyyMMddHHmmss");
            String encryptInfo = aesCbcEncrypt(data, key, true);
            String authInfoStr = "auth_info=" + URLEncoder.encode(encryptInfo, "UTF-8");
            return urlPath + "?" + authInfoStr;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static void checkParam(String url, String key) {
        if (StringUtils.isAnyEmpty(url, key)) {
            throw new IllegalArgumentException("url or key is illegal");
        }
    }

    private static String aesCbcEncrypt(String data, String key, boolean hasPoint) throws Exception {
        checkParam(data, key);

        byte[] realKey = get128BitKey(key);
        SecureRandom secureRand = new SecureRandom();
        byte[] ivBytes = new byte[16];
        secureRand.nextBytes(ivBytes);

        if (hasPoint) {
            return aesCbcEncrypt(data, ivBytes, realKey) + "." + bytesToHexString(ivBytes);
        } else {
            return aesCbcEncrypt(data, ivBytes, realKey) + bytesToHexString(ivBytes);
        }
    }

    private static String aesCbcEncrypt(String data, byte[] ivBytes, byte[] key) throws Exception {
        SecretKeySpec sk = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        if (ivBytes != null) {
            cipher.init(Cipher.ENCRYPT_MODE, sk, new IvParameterSpec(ivBytes));
        } else {
            cipher.init(Cipher.ENCRYPT_MODE, sk);
        }

        return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes("UTF-8")));
    }

    private static byte[] get128BitKey(String key) {
        byte[] result = null;

        if (key != null) {
            result = new byte[16];
            byte[] origin = key.getBytes();

            if (origin.length > 16) {
                System.arraycopy(origin, 0, result, 0, 16);
            } else {
                System.arraycopy(origin, 0, result, 0, origin.length);
            }
        }

        return result;
    }

    private static String encodeUrl(String str) {
        try {
            if (StringUtils.isNotEmpty(str)) {
                StringBuilder encodeStr = new StringBuilder(32);
                String[] tmpArray = str.split("/");
                for (int i = 0; i < tmpArray.length; i++) {
                    encodeStr.append(URLEncoder.encode(tmpArray[i], "UTF8")).append("/");
                }
                return encodeStr.toString();
            }
        } catch (Exception e) {
            throw new RuntimeException(String.format("Encode fail %s", e.getMessage()));
        }
        return str;
    }

    private static String getUtcTime(String dateTimePattern) {
        SimpleDateFormat foo = new SimpleDateFormat(dateTimePattern);
        java.util.Calendar cal = java.util.Calendar.getInstance();
        int zoneOffset = cal.get(java.util.Calendar.ZONE_OFFSET);
        int dstOffset = cal.get(java.util.Calendar.DST_OFFSET);
        cal.add(java.util.Calendar.MILLISECOND, -(zoneOffset + dstOffset));
        String time = foo.format(new Date(cal.getTimeInMillis()));

        return time;
    }

    private static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder("");
        if ((src == null) || (src.length <= 0)) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }
}