实现功能:这里主要说OSS上传
- 通常情况下移动端所展示的数据是从公司服务器(不是阿里云)请求得到的(下载)。
所以这里所实现的功能是在iOS移动端上传数据到阿里云服务器(OSS上传)。 - 从相册获取单图,多图,视频 以及录音,拍照,拍摄视频。
跟几乎所有的在使用第三方SDK时一样,一般只需要按照官方文档的几个步骤就能实现SDK里的功能。
OSS上传实现过程:分三步
前提条件:
- 导入阿里云SDK pod 'AliyunOSSiOS', '~> 2.6.0'
- 导入SDK头文件 #import <AliyunOSSiOS/OSSService.h>
1.第一步:初始化SDK (初始化SDK分3种:明文设置模式,STS鉴权模式,自签名模式)
1.1 明文设置:这个是自己在测试中使用的。正式项目中一般采用另外两种模式。我们公司采用的是STS鉴权模式。
表面上明文设置是要有ID和Secret。这个是在官网注册,一般是公司后台给你。其实不用设置就可以初始化。
代码如下:
id<OSSCredentialProvider> credential = [[OSSPlainTextAKSKPairCredentialProvider alloc] initWithPlainTextAccessKey:@"Access Key ID" secretKey:@"Access Key Secret"];
client = [[OSSClient alloc] initWithEndpoint:endPoint credentialProvider:credential];
1.2 STS鉴权模式:
何为鉴权模式?
请注意上面明文设置情况下是客户端直接与阿里云交互,只涉及到这两者。
STS模式下有三者参与:客户端,公司服务器,阿里云服务器。
交互流程:此时公司服务器作为中间者;
具体请看官方解释:看不明白也不要紧🕷
方案的详细描述如下:
- App用户登录。App用户身份是客户自己管理。客户可以自定义身份管理系统,也可以使用外部Web账号或OpenID。对于每个有效的App用户来说,AppServer可以确切地定义出每个App用户的最小访问权限。
- AppServer请求STS服务获取一个安全令牌(SecurityToken)。在调用STS之前,AppServer需要确定App用户的最小访问权限(用Policy语法描述)以及授权的过期时间。然后通过调用STS的AssumeRole(扮演角色)接口来获取安全令牌。角色管理与使用相关内容请参考RAM使用指南中的角色管理。
- STS返回给AppServer一个有效的访问凭证,App端称为FederationToken,包括一个安全令牌(SecurityToken)、临时访问密钥(AccessKeyId, AccessKeySecret)以及过期时间。
- AppServer将FederationToken返回给ClientApp。ClientApp可以缓存这个凭证。当凭证失效时,ClientApp需要向AppServer申请新的有效访问凭证。比如,访问凭证有效期为1小时,那么ClientApp可以每30分钟向AppServer请求更新访问凭证。
- ClientApp使用本地缓存的FederationToken去请求Aliyun Service API。云服务会感知STS访问凭证,并会依赖STS服务来验证访问凭证,并正确响应用户请求。
关于鉴权模式代码:
阿里云给出的demo是用苹果原生API NSURLSession来实现的,我这里用的是AFN实现
由于这种模式下需要有后台参与,后台会提供接口(参数请求体和URL),自己按照后台要求设置好了就行。
//STS鉴权模式
//设置请求体参数,这里的参数有两个,具体参数设置跟公司后台有关
NSString *mobile = @“/////////”;
NSString *secretString = [NSString stringWithFormat:@"%@",mobile];
//直接设置StsToken
id<OSSCredentialProvider> credential2 = [[OSSFederationCredentialProvider alloc] initWithFederationTokenGetter:^OSSFederationToken * {
OSSTaskCompletionSource * tcs = [OSSTaskCompletionSource taskCompletionSource];
//后台给的url链接
NSString *string = @"////////////////////////////////";
NSDictionary *dict = @{@"mobile":mobile,@"sign":secretString};
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//设置信任CA证书 在https传输情况下需要设置 不然会报错(如果CA证书是经过专业认证的,xcode里是不需要导入CA证书的,只需要设置以下几行代码就行)
AFSecurityPolicy * policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
policy.allowInvalidCertificates = YES;
policy.validatesDomainName = NO;
manager.securityPolicy = policy;
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", nil];
[manager POST:string parameters:dict progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"%@",responseObject);
self.responseObject = responseObject;
[tcs setResult:responseObject];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"%@",error);
if (error) {
[tcs setError:error];
return;
}
}];
//同步
[tcs.task waitUntilFinished];
if (tcs.task.error) {
NSLog(@"get token error: %@", tcs.task.error);
return nil;
}
else {
//获取token返回的参数
OSSFederationToken * token = [OSSFederationToken new];
token.tAccessKey = [self.responseObject objectForKey:@"AccessKeyId"];
token.tSecretKey = [self.responseObject objectForKey:@"AccessKeySecret"];
token.tToken = [self.responseObject objectForKey:@"SecurityToken"];
token.expirationTimeInGMTFormat = [self.responseObject objectForKey:@"Expiration"];
NSLog(@"get token: %@", token);
return token;
}
}];
//网络配置
OSSClientConfiguration * conf = [OSSClientConfiguration new];
conf.maxRetryCount = 2;
conf.timeoutIntervalForRequest = 30;
conf.timeoutIntervalForResource = 24 * 60 * 60;
client = [[OSSClient alloc] initWithEndpoint:endPoint credentialProvider:credential2 clientConfiguration:conf];
1.3 自签名模式
由于没有使用过这种模式,所以抱歉这里无从做说明。
第二步:上传文件(初始化成功后就可以开始上传了)
OSS支持两种文件格式上传,NSData和NSUrl。我这里是将所有文件转化成NSData然后再一一上传。
//上传请求类
OSSPutObjectRequest * request = [OSSPutObjectRequest new];
//文件夹名 后台给出
request.bucketName = @“//////////“;
//objectKey为文件名 一般自己拼接
request.objectKey = objectKey;
//上传数据类型为NSData
request.uploadingData = uploadData;
OSSTask * putTask = [client putObject:request];
[putTask continueWithBlock:^id(OSSTask *task) {
if (!task.error) {
//每次上传完一个文件都要回调
NSLog(@"上传成功!");
} else {
//上传失败后回调一次
NSLog(@"upload object failed, error: %@" , task.error);
}
return nil;
}];
//同步上传(去掉就是异步)因为我上传的文件有多种包括音视频,图片。而且OSS这边是每上传成功一个文件都要回调一次。比如我成功上传5张图片,那么就要回调5次。所以这个时候我就无法判断文件是否都上传完成。所以我就把这些上传的文件放在调度组里面,这样所有文件上传成功后我这边就知道了。如果上传放在调度组里,那么这里的同步上传就必须加上。
[putTask waitUntilFinished];
//上传进度
request.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
};
第三步:上传成功后设置回调链接(这一步不设置不影响上传,只是为了安全考虑在你上传成功后 后台需要有一个回调,所以才设置这个。一旦后台采用这种回调机制,那么你就必须得设置好回调,不然后台那边拿不到这个回调链接)
//上传回调参数和URL(这里是后台给的接口)
获取用户ID
NSString *userId = @“//////////”;
NSString *upUrl = @"////////////////////";
//不同类型的数据设置不同的文件名 根据文件名可以设置不同类型的回调参数
//头像
if ([objectKey rangeOfString:@"anchorImage"].location != NSNotFound){
//头像上传回调请求体 这里objectKey充当返回给后台URL的后缀
NSString *callBackBody = [NSString stringWithFormat:@"imageUrl=%@&mimeType=headimage&userId=%@",objectKey,userId];
// 设置回调参数
request.callbackParam = @{
@"callbackUrl":upUrl,
@"callbackBody":callBackBody,
@"callbackBodyType":@"application/json"
};
}
所以完整简单而又安全的OSS上传就只有以上三步,初始化SDK采用STS鉴权模式,上传文件,上传成功后设置回调链接。
刚开始做OSS上传的同学只需要简单两步就可以完成上传功能。
1.明文设置(初始化SDK)
2.上传 (具备条件,上传的文件是NSData或NSUrl,后台给bucketName即文件夹名)
建议自己在阿里云花几块钱注册一个OSS账号来测试自己上传的文件是否成功到阿里云服务器。
- 关于阿里云上传主要都在LCAliyunOSS里
- 头像和视频上传在LCPickerController里
- 多图相册上传使用的是第三方LPDQuoteImagesView
- 音频上传使用的是第三方IQAudioRecorderController
网友评论
还待完善:上传取消,上传失败【用户进入后台】,应用服务器数据库更新数据。
有1个问题请教:您OSS上传文件成功后什么通知给App服务器存SQL数据库?纠结的是:1. 如果是上传之后通知,万一App服务器暂时不可用,OSS上的文件不就是永久垃圾了;2. 如果是上传之前通知,OSS上传失败得在删除一遍;不知如何是好,作者有何种建议?
Ps:工程名称建议还是英文吧?