客户端上传指引

最近更新时间:2025-06-13 16:30:52

我的收藏
本文主要提供专业版应用客户端上传指引。

适用场景

终端用户将客户端本地视频上传到云点播,适用于 UGC、PGC 等场景。

上传方式

客户端对密钥安全性要求较高,我们推荐通过专业版预置域名使用临时凭证上传,支持方式如下:
上传方式
上传域名
上传凭证
支持操作
存储桶预置域名
[BucketId].vodpro.[存储地域].eovod.com
临时凭证
上传至指定存储桶
应用预置域名
[SubAppId].vodpro-upload.com
临时凭证
上传至指定存储桶
就近上传至应用内某区域的存储桶

使用临时凭证上传文件

临时凭证通常用于对密钥安全性要求较高的场景。客户端使用临时凭证上传文件至专业版存储整体流程如下图:

1. 申请上传临时凭证
1.1 客户端向 App 后台申请上传临时凭证。
1.2 服务端调用云点播专业版服务 申请上传临时凭证
2. 上传文件
客户端使用临时凭证上传文件至云点播专业版存储。

准备工作

1. 创建专业版应用和存储桶
云点播控制台 创建好专业版应用和存储桶,具体操作步骤参见 快速入门创建存储桶 文档。
2. 获取腾讯云账号永久密钥对
2.1 登录腾讯云控制台,选择访问管理 > 访问密钥 > API 密钥管理,进入“API 密钥管理” 页面。
2.2 获取云 API 密钥。如果您尚未创建密钥,则单击新建密钥即可创建一对 SecretIdSecretKey

服务端申请上传临时凭证

客户服务端使用 SecretIdSecretKey调用 申请上传临时凭证 接口,获取到上传临时凭证后派发给客户端使用。
假设专业版应用 ID 为 1234567890 ,存储桶的存储地域为 ap-guangzhou,存储桶 ID 为 bucketid1
服务端申请 bucketid1存储桶上传 upload/demo.mp4的临时凭证,实现如下:
GO
Java
C++
Python
// Package main
package main

import (
"context"
"encoding/json"
"fmt"
"log"
"net/url"

"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
vod20240718 "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod/v20240718"
)

const (
appId = 251000000 // 腾讯云账号 APPID
subAppId = 1234567890 // 云点播专业版应用 APPID
bucketId = "bucketid1" // 云点播专业版应用存储桶的 ID
fileKey = "upload/demo.mp4" // 上传到存储后的文件 KEY,包含完整路径和文件名,例如 upload/demo.mp4
)

// createStorageCredentialsPolicy 创建存储凭证策略
type createStorageCredentialsPolicy struct {
Statement []policyStatement `json:"statement"`
Version string `json:"version"`
}

// policyStatement 策略语句
type policyStatement struct {
Action []string `json:"action"`
Effect string `json:"effect"`
Resource []string `json:"resource"`
}

// cred 临时凭证
type cred struct {
AccessKeyId string
SecretAccessKey string
SessionToken string
}

// getCredential 获取临时凭证
func getCredential(context.Context) (*cred, error) {
// 1. 获取临时凭证
// 1.1 初始化调用腾讯云 API 对象
credential := common.NewCredential(
"SecretId", // 腾讯云账号 SecretId
"SecretKey", // 腾讯云账号 SecretKey
)
prof := profile.NewClientProfile()
vodClient, err := vod20240718.NewClient(credential, "ap-guangzhou", prof)
if err != nil {
log.Fatalf("create VOD client fail: %+v", err)
return nil, fmt.Errorf("create VOD client fail: %w", err)
}

// 1.2 构造申请上传临时凭证请求
policy := createStorageCredentialsPolicy{
Statement: []policyStatement{{
Action: []string{ // 当前仅支持如下 action,可以只申请其中一部分
"name/vod:PutObject",
"name/vod:ListParts",
"name/vod:PostObject",
"name/vod:CreateMultipartUpload",
"name/vod:UploadPart",
"name/vod:CompleteMultipartUpload",
"name/vod:AbortMultipartUpload",
"name/vod:ListMultipartUploads",
},
Effect: "allow",
Resource: []string{
fmt.Sprintf("qcs::vod:%s:uid/%d:prefix//%d/%s/%s",
"ap-guangzhou", // 存储桶所在地域
appId, // 腾讯云账号 APPID
subAppId, // 云点播专业版应用 APPID
bucketId, // 云点播专业版应用存储桶的 ID
fileKey, // 上传到存储后的文件 KEY,包含完整路径和文件名,例如 upload/demo.mp4
),
},
}},
Version: "2.0",
}
req := vod20240718.NewCreateStorageCredentialsRequest()
req.SubAppId = common.Uint64Ptr(subAppId)
policyStr, _ := json.Marshal(policy)
req.Policy = common.StringPtr(url.QueryEscape(string(policyStr)))

// 1.3 申请上传临时凭证
resp, err := vodClient.CreateStorageCredentials(req)
if err != nil {
log.Fatalf("create storage credentials fail: %+v", err)
return nil, fmt.Errorf("create storage credentials fail: %w", err)
}
log.Printf("create storage credentials success: %+v", resp)
creds := resp.Response.Credentials
return &cred{
AccessKeyId: *creds.AccessKeyId,
SecretAccessKey: *creds.SecretAccessKey,
SessionToken: *creds.SessionToken,
}, nil
}
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.vod.v20240718.VodClient;
import com.tencentcloudapi.vod.v20240718.models.CreateStorageCredentialsRequest;
import com.tencentcloudapi.vod.v20240718.models.CreateStorageCredentialsResponse;

import org.json.JSONArray;
import org.json.JSONObject;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

/**
* 凭证辅助类,负责获取临时存储凭证
*/
public class CredentialHelper {
// 常量定义
private static final long APP_ID = 251000000; // 腾讯云账号 APPID
private static final long SUB_APP_ID = 1234567890; // 云点播专业版应用 APPID
private static final String BUCKET_ID = "bucketid1"; // 云点播专业版应用存储桶的 ID
private static final String FILE_KEY = "upload/demo.mp4"; // 上传到存储后的文件 KEY
private static final String REGION = "ap-guangzhou"; // 存储桶所在地域

/**
* 凭证对象,存储临时凭证信息
*/
public static class Cred {
private final String accessKeyId;
private final String secretAccessKey;
private final String sessionToken;

public Cred(String accessKeyId, String secretAccessKey, String sessionToken) {
this.accessKeyId = accessKeyId;
this.secretAccessKey = secretAccessKey;
this.sessionToken = sessionToken;
}

public String getAccessKeyId() {
return accessKeyId;
}

public String getSecretAccessKey() {
return secretAccessKey;
}

public String getSessionToken() {
return sessionToken;
}
}

/**
* 获取临时凭证
*
* @return 临时凭证对象
* @throws Exception 如果获取凭证失败
*/
public static Cred getCredential() throws Exception {
try {
// 1. 初始化腾讯云 API 客户端
Credential credential = new Credential("SecretId", "SecretKey"); // 腾讯云账号 SecretId 和 SecretKey
ClientProfile clientProfile = new ClientProfile(); // 客户端配置
VodClient vodClient = new VodClient(credential, "ap-guangzhou", clientProfile); // 创建 VodClient 对象

// 2. 构造并编码策略
String policyJson = createPolicyJson();
String encodedPolicy = URLEncoder.encode(policyJson, StandardCharsets.UTF_8.name());

// 3. 创建并发送请求
CreateStorageCredentialsRequest req = new CreateStorageCredentialsRequest();
req.setSubAppId(SUB_APP_ID); // 云点播专业版应用 APPID
req.setPolicy(encodedPolicy); // 策略

// 4. 获取响应并返回凭证
CreateStorageCredentialsResponse resp = vodClient.CreateStorageCredentials(req);

return new Cred(
resp.getCredentials().getAccessKeyId(),
resp.getCredentials().getSecretAccessKey(),
resp.getCredentials().getSessionToken());
} catch (TencentCloudSDKException e) {
System.err.println("获取存储凭证失败: " + e.getMessage());
throw new Exception("获取存储凭证失败", e);
}
}

/**
* 创建策略JSON字符串,使用 org.json 库
*
* @return 策略JSON字符串
*/
private static String createPolicyJson() {
// 构建资源路径
String resource = String.format(
"qcs::vod:%s:uid/%d:prefix//%d/%s/%s",
REGION,
APP_ID,
SUB_APP_ID,
BUCKET_ID,
FILE_KEY);

// 构建操作列表
String[] actions = {
"name/vod:PutObject",
"name/vod:ListParts",
"name/vod:PostObject",
"name/vod:CreateMultipartUpload",
"name/vod:UploadPart",
"name/vod:CompleteMultipartUpload",
"name/vod:AbortMultipartUpload",
"name/vod:ListMultipartUploads"
};

// 使用 JSONObject 构建 JSON
JSONObject policy = new JSONObject();
policy.put("version", "2.0");

JSONArray statements = new JSONArray();
JSONObject statement = new JSONObject();

JSONArray actionArray = new JSONArray();
for (String action : actions) {
actionArray.put(action);
}
statement.put("action", actionArray);

statement.put("effect", "allow");

JSONArray resources = new JSONArray();
resources.put(resource);
statement.put("resource", resources);

statements.put(statement);
policy.put("statement", statements);

return policy.toString();
}
}
#include <tencentcloud/core/TencentCloud.h>
#include <tencentcloud/core/profile/ClientProfile.h>
#include <tencentcloud/core/profile/HttpProfile.h>
#include <tencentcloud/core/Credential.h>
#include <tencentcloud/vod/v20240718/VodClient.h>
#include <tencentcloud/vod/v20240718/model/CreateStorageCredentialsRequest.h>
#include <tencentcloud/vod/v20240718/model/CreateStorageCredentialsResponse.h>
#include <string>
#include <sstream>
#include <iomanip>
#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

const uint64_t APP_ID = 251000000; // 腾讯云账号 APPID
const uint64_t SUB_APP_ID = 1234567890; // 云点播专业版应用 APPID
const std::string BUCKET_ID = "bucketid1"; // 云点播专业版应用存储桶的 ID
const std::string REGION = "ap-guangzhou"; // 云点播专业版应用存储桶地域
const std::string OBJECT_KEY = "upload/demo.mp4"; // 申请权限的存储文件 KEY

// 凭证结构体
struct Credential
{
std::string accessKeyId;
std::string secretAccessKey;
std::string sessionToken;
};

// URL 编码函数
std::string UrlEncode(const std::string &value)
{
std::ostringstream escaped;
escaped.fill('0');
escaped << std::hex;

for (char c : value)
{
if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~')
{
escaped << c;
}
else
{
escaped << std::uppercase;
escaped << '%' << std::setw(2) << int((unsigned char)c);
escaped << std::nouppercase;
}
}

return escaped.str();
}

// 获取临时凭证
Credential GetCredential()
{
// 初始化腾讯云 SDK
TencentCloud::InitAPI();

// 创建 VOD 客户端
TencentCloud::Credential credential("SecretId", "SecretKey"); // 填入腾讯云账号 SecretId 和 SecretKey
TencentCloud::HttpProfile httpProfile;
TencentCloud::ClientProfile clientProfile;
clientProfile.SetHttpProfile(httpProfile);

TencentCloud::Vod::V20240718::VodClient client(credential, "ap-guangzhou", clientProfile);

// 构建策略
json policy_json = {
{"statement", {{{"action", {"name/vod:PutObject", "name/vod:ListParts", "name/vod:PostObject", "name/vod:CreateMultipartUpload", "name/vod:UploadPart", "name/vod:CompleteMultipartUpload", "name/vod:AbortMultipartUpload", "name/vod:ListMultipartUploads"}}, {"effect", "allow"}, {"resource", {"qcs::vod:" + REGION + ":uid/" + std::to_string(APP_ID) + ":prefix//" + std::to_string(SUB_APP_ID) + "/" + BUCKET_ID + "/" + OBJECT_KEY}}}}},
{"version", "2.0"}};
std::string policy = policy_json.dump();

// 创建请求对象
TencentCloud::Vod::V20240718::Model::CreateStorageCredentialsRequest req;
req.SetSubAppId(SUB_APP_ID);
req.SetPolicy(UrlEncode(policy));

// 发送请求
auto outcome = client.CreateStorageCredentials(req);
if (!outcome.IsSuccess())
{
std::cerr << "Failed to get storage credentials: " << outcome.GetError().GetErrorMessage() << std::endl;
TencentCloud::ShutdownAPI();
exit(1);
}

// 提取凭证
auto response = outcome.GetResult();
auto creds = response.GetCredentials();

Credential result;
result.accessKeyId = creds.GetAccessKeyId();
result.secretAccessKey = creds.GetSecretAccessKey();
result.sessionToken = creds.GetSessionToken();

// 清理腾讯云 SDK
TencentCloud::ShutdownAPI();

return result;
}
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import json
import urllib.parse
from typing import NamedTuple

from tencentcloud.common import credential
from tencentcloud.common.profile import client_profile
from tencentcloud.vod.v20240718 import vod_client, models

# 常量定义
APP_ID = 251000000 # 腾讯云账号 APPID
SUB_APP_ID = 1234567890 # 云点播专业版应用 APPID
BUCKET_ID = "bucketid1" # 云点播专业版应用存储桶的 ID
OBJECT_KEY = "upload/demo.mp4" # 上传到存储后的文件 KEY
REGION = "ap-guangzhou" # 地域


class Credential(NamedTuple):
"""临时凭证"""

access_key_id: str
secret_access_key: str
session_token: str


def get_credential() -> Credential:
"""获取临时凭证"""
# 1. 初始化调用腾讯云 API 对象
cred = credential.Credential(
"SecretId", # 腾讯云账号 SecretId
"SecretKey", # 腾讯云账号 SecretKey
)
prof = client_profile.ClientProfile()
vod_cli = vod_client.VodClient(cred, "ap-guangzhou", prof)

# 2. 构造申请上传临时凭证请求
policy = {
"statement": [
{
"action": [
"name/vod:PutObject",
"name/vod:ListParts",
"name/vod:PostObject",
"name/vod:CreateMultipartUpload",
"name/vod:UploadPart",
"name/vod:CompleteMultipartUpload",
"name/vod:AbortMultipartUpload",
"name/vod:ListMultipartUploads",
],
"effect": "allow",
"resource": [f"qcs::vod:{REGION}:uid/{APP_ID}:prefix//{SUB_APP_ID}/{BUCKET_ID}/{OBJECT_KEY}"],
}
],
"version": "2.0",
}

req = models.CreateStorageCredentialsRequest()
req.SubAppId = SUB_APP_ID
req.Policy = urllib.parse.quote(json.dumps(policy))

# 3. 申请上传临时凭证
resp = vod_cli.CreateStorageCredentials(req)
creds = resp.Credentials
return Credential(
access_key_id=creds.AccessKeyId,
secret_access_key=creds.SecretAccessKey,
session_token=creds.SessionToken,
)

使用 SDK 上传文件

下面介绍在常用的客户端 SDK 中,如何进行适配以上传文件至专业版应用的存储桶。

域名

专业版为每个应用预置了一个上传加速域名,应用下所有存储桶均可使用该域名进行上传。
示例使用的应用上传加速域名均为:1234567890.vodpro-upload.com

使用 VOD SDK 上传文件

App 客户端使用获取到的临时凭证,将文件上传至云点播专业版存储,详情参见:Flutter 上传 SDK