本文介绍如何使用iOS SDK将媒体文件从本地上传至点播存储。
前提条件
项目 | 要求 |
最低 iOS 版本 | iOS 12.0 |
开发语言 | Objective-C(Swift 工程通过 Bridging Header 桥接) |
阿里云账号 | 已开通视频点播服务 |
鉴权服务 | 已准备好可签发上传凭证(UploadAuth)的后端服务 |
集成SDK
集成方式
在 Podfile 中加入:
platform :ios, '12.0'
target 'YourApp' do
pod 'VODUpload', '~> 2.0'
end执行:
pod repo update
pod installSDK 会自动拉取底层 AliyunOSSiOS 依赖。
项目配置
podspec 已声明以下系统库,使用 CocoaPods 集成时自动链接:
SystemConfiguration.framework
MobileCoreServices.framework
CoreMedia.framework
AVFoundation.framework
CoreTelephony.framework
libresolv.tbdSDK 自带 PrivacyInfo.xcprivacy 隐私清单,随 Pod 集成自动注入到 VODUpload.bundle/PrivacyInfo.xcprivacy,无需额外配置。
按需引入头文件:
#import <VODUpload/VODUploadV2Client.h>
#import <VODUpload/VODUploadConfig.h>
#import <VODUpload/VODAuthContext.h>
#import <VODUpload/VODGetAuthCallback.h>
#import <VODUpload/VODUploadOptions.h>
#import <VODUpload/VODUploadResult.h>
#import <VODUpload/VODUploadError.h>
#import <VODUpload/VODVideoMeta.h>
#import <VODUpload/VODImageMeta.h>
#import <VODUpload/VODUploadTask.h>基础设置
初始化上传实例
VODUploadConfig 使用 property 直接设置,调用 +uploaderWithConfig: 工厂方法创建实例:
VODUploadConfig *config = [[VODUploadConfig alloc] init];
config.getAuth = getAuth; // 必填:鉴权回调,详见"回调处理"
VODUploadV2Client *uploader = [VODUploadV2Client uploaderWithConfig:config];uploader 实例应作为属性持有(不能是局部变量,否则会被 ARC 释放导致回调丢失)。可复用同一实例并发上传多个文件,生命周期结束时调用 [uploader dispose] 释放资源。
上传控制
调用 uploadFile:options:callback: 启动一次上传,返回 VODUploadTask 句柄用于取消:
VODVideoMeta *meta = [[VODVideoMeta alloc] init];
meta.title = @"我的视频";
meta.tags = @"demo";
meta.cateId = @(1000);
VODUploadOptions *options = [[VODUploadOptions alloc] init];
options.videoMeta = meta;
options.onProgress = ^(float percent, int64_t uploaded, int64_t total) {
NSLog(@"%.1f%%", percent * 100);
};
VODUploadTask *task = [uploader uploadFile:filePath
options:options
callback:^(VODUploadResult *r, VODUploadError *e) {
if (e) {
NSLog(@"%@: %@", e.errorCode, e.errorMessage);
return;
}
NSLog(@"videoId=%@ uploadTaskId=%@ etag=%@ requestId=%@ durationMs=%lld",
r.videoId, r.uploadTaskId, r.etag, r.requestId, r.durationMs);
}];
// 中途取消(默认开启断点续传,下次同文件 uploadFile 自动续传)
[task cancel];
// task.uploadTaskId 可用于关联日志、对接埋点图片上传:SDK 根据文件扩展名(jpg / jpeg / png / gif / bmp / webp / heic)或显式 options.imageMeta != nil 自动走图片链路,成功回调中 imageId / imageUrl 有值:
VODImageMeta *imgMeta = [[VODImageMeta alloc] init];
imgMeta.imageType = @"cover";
imgMeta.title = @"封面";
VODUploadOptions *opts = [[VODUploadOptions alloc] init];
opts.imageMeta = imgMeta;
[uploader uploadFile:imagePath options:opts callback:cb];VODVideoMeta 的描述字段为 desc(非 description,避免与 Objective-C 保留方法冲突)。
回调处理
v2 通过统一的 VODGetAuthCallback block 向业务方索取上传凭证。SDK 在以下时机调用 getAuth,并通过 VODAuthContext.kind告知所需凭证类型:
Kind | 触发时机 | 业务方应调用的 OpenAPI |
| 首次上传一个视频文件 | |
| 续传 / 凭证刷新 | |
| 上传图片 |
业务方只需把后端 OpenAPI 返回的原始 JSON 原样传入 completion。SDK 按 OpenAPI 原始字段名(大小写敏感)读取以下键:
Kind | 必须包含的字段 |
|
|
|
|
字段名大小写敏感,请直接转发 OpenAPI 响应;自行重命名为 videoId / imageUrl / image_url 会导致 SDK 解析为 nil。
VODGetAuthCallback getAuth = ^(VODAuthContext *ctx,
void (^completion)(NSDictionary *result, NSError *error)) {
switch (ctx.kind) {
case VODAuthKindCreateVideo:
[YourBackend createUploadVideo:ctx.fileName
fileSize:ctx.fileSize
completion:^(NSDictionary *json, NSError *err) {
completion(json, err);
}];
break;
case VODAuthKindRefreshVideo:
[YourBackend refreshUploadVideo:ctx.videoId
completion:^(NSDictionary *json, NSError *err) {
completion(json, err);
}];
break;
case VODAuthKindCreateImage:
[YourBackend createUploadImage:ctx.fileName
completion:^(NSDictionary *json, NSError *err) {
completion(json, err);
}];
break;
}
};高级设置
上传加速
将 VODVideoMeta.userData 设置为下面的 JSON,VOD 服务端在签发 UploadAddress 时会自动返回 OSS 全球传输加速节点(oss-accelerate.aliyuncs.com),SDK 直传到加速节点完成上传:
VODVideoMeta *meta = [[VODVideoMeta alloc] init];
meta.title = @"我的视频";
meta.userData = @"{\"Type\":\"oss\",\"Domain\":\"oss-accelerate.aliyuncs.com\"}";上传加速能力依赖 OSS 全球传输加速,需在 OSS 控制台对 Bucket 开启传输加速。详情请参见通过传输加速访问OSS 。
上传转码
通过 VODVideoMeta 指定转码模板组或工作流:
VODVideoMeta *meta = [[VODVideoMeta alloc] init];
meta.title = @"我的视频";
meta.desc = @"视频描述"; // 注意:是 desc,不是 description
meta.coverUrl = @"https://example.com/cover.jpg";
meta.cateId = @(1000);
meta.tags = @"tag1,tag2";
meta.storageLocation = @"<可选:自定义存储区域>";
meta.templateGroupId = @"<你的模板组 ID>"; // 转码模板组
meta.workflowId = @"<你的工作流 ID>"; // 工作流(可选)
meta.appId = @"<可选:应用 ID>";VODVideoMeta 支持的字段:title / desc / coverUrl / cateId / tags / userData / storageLocation / templateGroupId / workflowId / appId。所有字段均可选,最终透传到 CreateUploadVideo。
上传完成后 VOD 服务端根据模板组对源视频转码。若不希望触发转码,业务后端在 CreateUploadVideo 时传入"无转码"模板组即可。
超时重试
VODUploadConfig *config = [[VODUploadConfig alloc] init];
config.getAuth = getAuth;
config.timeout = 60; // 单位:秒,默认 60
config.maxRetryCount = 2; // 默认 2 次timeout 控制单次 OSS 请求的连接 / 读写超时(NSTimeInterval,单位秒);maxRetryCount 控制 OSS 请求在网络异常时的重试次数。
Android timeout 单位是毫秒,iOS 单位是秒,跨端集成时注意区分。
签名版本
1config.signature = @"v4"; // 默认 @"v4",可选 @"v1"OSS V4 签名是当前推荐版本,自 2025-09-01 起新建 Bucket 强制使用 V4 签名,存量客户也建议尽快迁移。仅当业务方依赖的 Bucket 仍只支持 V1 签名时才需显式设置 @"v1"。
断点续传
默认开启。SDK 使用 (lastModified, fileName, fileSize) 三元组作为续传 key,自动持久化到本地 Caches 目录:
场景 | SDK 行为 |
上传途中调用 | 保留续传记录,下次同文件 |
App 崩溃 / 后台被杀 | 保留续传记录,下次冷启同文件 |
文件指纹任一变化 | 视为新文件,全新上传 |
OSS uploadId 过期 | SDK 自动清除旧记录,重新走 |
如需关闭:
config.checkpoint = NO;分片上传
通过 partSize 控制分片大小、parallel 控制并发分片数:
// 全局配置
config.partSize = 1024 * 1024; // 默认 1MB
config.parallel = 4; // 默认 4
// 单次任务覆盖
VODUploadOptions *options = [[VODUploadOptions alloc] init];
options.videoMeta = meta;
options.partSize = 2 * 1024 * 1024;
options.parallel = 6;设置点播服务地域
1config.region = @"cn-shanghai"; // 默认 cn-shanghai支持的 region 列表见 点播地域标识。
数据上报
SDK 默认开启上传链路埋点用于产品质量监控,仅采集上传过程的运行指标,不包含文件内容。如需关闭:
config.reportEnabled = NO; // 默认 YES错误处理
VODUploadError 继承自 NSError,错误码采用 UPLOAD.{LAYER}.{TYPE} 三段式:
LAYER | 错误码 | 含义 |
AUTH |
| getAuth 回调失败 |
AUTH |
| UploadAuth 解码失败 |
AUTH |
| 凭证过期 |
OSS |
| OSS 拒绝访问(权限/签名) |
OSS |
| Bucket 不存在 |
OSS |
| uploadId 过期(SDK 自动 fallback) |
OSS |
| OSS 上传失败 |
OSS |
| OSS 分片合并失败 |
NETWORK |
| 网络超时 |
NETWORK |
| 网络不可达 |
FILE |
| 文件不存在 |
FILE |
| 文件为空 |
CANCEL |
| 用户取消 |
INTERNAL |
| 实例已 dispose |
INTERNAL |
| 配置非法 |
公开属性:
NSString *errorCode— 错误码NSString *errorMessage— 错误信息NSError *cause— 底层 OSS 异常NSString *uploadTaskId— 上传任务 IDNSString *suggestion— SDK 内置的修复建议
if ([error.errorCode hasPrefix:@"UPLOAD.AUTH."]) {
// 提醒用户检查后端鉴权
} else if ([error.errorCode isEqualToString:VODErrorCodeOssUploadFailed]) {
// 重试或提示用户检查网络
}
NSLog(@"%@ : %@ (cause=%@, suggestion=%@)",
error.errorCode, error.errorMessage, error.cause, error.suggestion);常见问题
能否同时发起多个 uploadFile
可以,每个 task 独立。建议根据网络情况控制并发数,避免与 parallel 叠加放大上行带宽压力。
取消后再次 uploadFile 没有续传
请按以下步骤排查:
确认是否同一文件路径;
确认文件 lastModified / size 是否变化;
确认
config.checkpoint是否为YES;确认uploadId 是否过期(响应
NoSuchUpload时 SDK 自动 fallback 全新上传,属预期行为)。
App Store Connect 审核被拒,提示 Missing Privacy Manifest
SDK 已自带 PrivacyInfo.xcprivacy 并随 Pod 自动注入。同时 App 自身也需声明所使用的 Required Reason API。
uploader 创建后回调不触发
确认 uploader 不是局部变量。VODUploadV2Client 实例需要作为 self 的属性持有,否则会被 ARC 提前释放。