前言

最近在做项目时,后台的人说修改个人资料时头像要通过OSS上传。我当时就懵逼了,这是咋回事,是一种协议吗?一查才知道不是,但除了阿里的官方文档,也查不到太多的资料。于是只能一步一步探索,并且记录下来希望能有点j用。

  • OSS是什么,有什么好处。

简单点说,OSS就是把数据放到阿里的服务器(以下简称为云服)里存储的服务。

好处:

  1. 成本低

其收费规则:

阿里云定价文档 对象存储OSS仅按照您的实际使用容量收费,您无需预先购买存储和流量容量,随着您业务的发展,您将享受到更多的基础设施成本优势。

好处显而易见,收费低,减轻了我们后台服务器(以下简称为后服)的压力。

  1. 数据安全,多重备份。
  2. 数据处理服务。图片处理、音视频转码、内容加速分发、鉴黄服务、归档服务等。
  3. 数据自动管理生命周期等。
  • OSS流程原理

不用OSS时,如果我们要上传照片到后服,只需要发起一个请求。

// 1.处理图片
// 2.上传到后服
复制代码

采用OSS后,需要发起两个请求。

// 1.处理图片
// 2.上传到云服,成功后拼接图片路径url
// 3.后服接口中图片参数应为NSString,把第2步拼接的url作为参数上传到后服
复制代码

使用OSS

  1. 准备工作

开通OSS并配置云服,这种事通常都是由后台的人管的吧。

所以问后台的人,拿到AccessKeySecretKey。还有Bucket(存储空间,相当于主目录),内、外网用的Endpoint(访问域名)。

内、外网区别在于:内网是用于同一Bucket阿里云产品之间,例如把图片拿去分析之类的操作。外网就是我们把图片上传到云服以及不同Bucket之类的操作。本文探究的是外网上传图片操作。



  1. 上传照片

直接上代码

@interface FHProfileInfoViewModel()

@property (nonatomic, strong) OSSClient *client;

@end

@implementation FHProfileInfoViewModel

- (void)aliyunWithFileName:(NSString *)fileName {

    [MBProgressHUD fh_showMessage:@"正在修改"];
    
    OSSPutObjectRequest * put = [OSSPutObjectRequest new];
    put.bucketName = @"你项目的bucketName,相当于主目录";
    //  objectKey为云服储存的文件名
    put.objectKey = fileName;
    UIImage *testImage = [UIImage imageNamed:@"test"];
    NSData *testData = UIImageJPEGRepresentation(testImage, 0.1);
    put.uploadingData = testData;
    // 此处可查看上传进度
//    put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
//        NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
//    };
    OSSTask * putTask = [self.client putObject:put];
    [putTask continueWithBlock:^id(OSSTask *task) {
        if (!task.error) {
            NSLog(@"upload object success!");
            [MBProgressHUD fh_hideHUD];
            // 1.拼接url
            // 2.调用后台接口
            
        } else {
            NSLog(@"upload object failed, error: %@" , task.error);
            [MBProgressHUD fh_hideHUD];
            [MBProgressHUD fh_showError:@"修改失败"];
        }
        return nil;
    }];
    // 可以等待任务完成
    [putTask waitUntilFinished];
}

- (OSSClient *)client {
    if (!_client) {
        NSString *endpoint = @"你项目的endpoint";
        NSString *accessKeyid = @"你项目的accessKeyid";
        NSString *secretKeyId = @"你项目的secretKeyId";
        NSString *securityToken = @"";// 可空 看后台
        id<OSSCredentialProvider> credential = [[OSSStsTokenCredentialProvider alloc] initWithAccessKeyId:accessKeyid secretKeyId:secretKeyId securityToken:securityToken];
        _client = [[OSSClient alloc] initWithEndpoint:endpoint credentialProvider:credential];
    }
    return _client;
}

@end
复制代码

1⃣️官方文档建议OSSClient全局一个,注意配置好相应数据。

2⃣️objectKey为文件名。

3⃣[putTask waitUntilFinished];类似GCD栏杆函数。这里因为要等上传成功后拼接url,再上传到后台,所以调用。

4⃣️最后来说说上传成功后的url拼接。

刚开始测的时候,发现上传成功的回调里,并未找到。上网搜也搜不到教程。后来听了大佬说才知道原来是这样。

NSString *picUrlStr = [NSString stringWithFormat:@"http://%@.%@/%@", bucketName, endpoint, objectName];
    // 即"http://" + bucketName + "." + this.endpoint + "/" + objectName;
复制代码

再说说一些特别点

  1. OSS服务里,不存在文件夹这种概念。但是我们命名objectName时,可以带上/(不能以"/"或""开头),看上去就像文件夹管理一样。
  2. 如果传了相同objectName的文件,将会覆盖。
  3. 图片文件名如果没有没有加上.png,那么在浏览器里打开时会直接下载。如果加了,会展示出来。

亲测,- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder,这个方法未加.png也能成功显示。

所以名字见仁见智吧。如果有需要就和后台、安卓的人商量好命名规则。