human: 如何处理七牛云的对象存储Objective-C SDK

gpt: [对象存储](https://developer.qiniu.com/kodo) > SDK 下载 > Objective-C SDK

#  Objective-C SDK

最近更新时间: 2024-08-05 18:23:52

Objective-C SDK 为客户端 SDK，没有包含 token 生成实现，为了安全，token 都建议通过网络从服务端获取
具体生成代码可以参考七牛服务端官方 SDK 。支持 Mac 和 iOS，会根据文件大小自动选择表单上传还是断点续上传。

  * [Objective-C SDK 下载地址 __](https://github.com/qiniu/objc-sdk/releases)
  * [Objective-C SDK 源码地址 __](https://github.com/qiniu/objc-sdk)
  * [Objective-C SDK 单元测试 __](https://github.com/qiniu/objc-sdk/tree/master/QiniuSDKTests)

**版本**

Qiniu SDK 版本 | 最低 iOS 版本 | 最低 OS X 版本 | Notes  
---|---|---|---  
[ 8.8.x __](https://github.com/qiniu/objc-sdk/tree/v8.5.0)|  iOS 9 | OS X 10.15 | Xcode 最低版本 11.  
[ 8.7.x __](https://github.com/qiniu/objc-sdk/tree/v8.5.0)|  iOS 9 | OS X 10.15 | Xcode 最低版本 11.  
[ 8.6.x __](https://github.com/qiniu/objc-sdk/tree/v8.5.0)|  iOS 9 | OS X 10.15 | Xcode 最低版本 11.  
[ 8.5.x __](https://github.com/qiniu/objc-sdk/tree/v8.5.0)|  iOS 7 | OS X 10.15 | Xcode 最低版本 11.  
[ 8.4.x __](https://github.com/qiniu/objc-sdk/tree/v8.4.0)|  iOS 7 | OS X 10.15 | Xcode 最低版本 11.  
[ 8.3.x __](https://github.com/qiniu/objc-sdk/tree/v8.3.0)|  iOS 7 | OS X 10.15 | Xcode 最低版本 11.  
[ 8.2.x __](https://github.com/qiniu/objc-sdk/tree/v8.2.0)|  iOS 7 | OS X 10.15 | Xcode 最低版本 11.  
[ 8.1.x __](https://github.com/qiniu/objc-sdk/tree/v8.1.0)|  iOS 7 | OS X 10.15 | Xcode 最低版本 11.  
[ 8.0.x __](https://github.com/qiniu/objc-sdk/tree/v8.0.0)|  iOS 7 | OS X 10.15 | Xcode 最低版本 11.  
[ 7.4.x __](https://github.com/qiniu/objc-sdk/tree/v7.4.0)|  iOS 7 | OS X 10.9 | Xcode 最低版本 6.  
[ 7.3.x __](https://github.com/qiniu/objc-sdk/tree/v7.3.0)|  iOS 7 | OS X 10.9 | Xcode 最低版本 6.  
[ 7.2.x __](https://github.com/qiniu/objc-sdk/tree/v7.2.0)|  iOS 7 | OS X 10.9 | Xcode 最低版本 6.  
[7.1.x / AFNetworking-3.x __](https://github.com/qiniu/objc-sdk/tree/AFNetworking-3.x)|  iOS 7 | OS X 10.9 | Xcode 最低版本 6.  
[7.0.x / AFNetworking-2.x __](https://github.com/qiniu/objc-sdk/tree/7.0.x/AFNetworking-2.x)|  iOS 6 | OS X 10.8 | Xcode 最低版本 5.  
[7.x / AFNetworking-1.x __](https://github.com/qiniu/objc-sdk/tree/AFNetworking-1.x)|  iOS 5 | OS X 10.7 | Xcode 最低版本 5.  
[6.x __](https://github.com/qiniu/ios-sdk)|  iOS 6 | None | Xcode 最低版本 5.  
  
# 1 安装

## 1.1 使用 Cocoapods 进行安装

    
    
    pod "Qiniu", "~> 8.8.0"
    

## 1.2 通过 Swift Package Manager

    
    
    App 对接:
    File -> Swift Packages -> Add Package Dependency，输入库链接，选择相应版本即可。
    库链接: https://github.com/qiniu/objc-sdk
    
    库对接:
    let package = Package(
        dependencies: [
            .package(url: "https://github.com/qiniu/objc-sdk", from: "8.8.0")
        ],
        // ...
    )
    
    库引入方式：
    import QiniuSDK
    

# 2 推荐的使用姿势

iOS SDK 作为移动端的 SDK，在使用时会被嵌入到移动端的应用中，为了保证信息的安全以及业务的灵活性，我们给出以下几点建议：

### 2.1 AccessKey 和 SecretKey 下发

账户以及 iam 子账户的密钥对 AccessKey 和 SecretKey
不要固化在客户端中，其涉及相关参数通过用户自己的业务服务端来生成并下发（比如上传的 Token）。业务服务端集中管理 AccessKey 和
SecretKey ，避免泄漏；其次 AccessKey 、SecretKey 和客户端应用需解耦，其因泄露更换时不会产生不必要麻烦。

### 2.2 上传域名下发，并可以下发多个域名

SDK 上传过程：

  1. 获取七牛 Bucket 的上传域名； 
     * 指定域名。通过指定区域 id 或直接给上传域名列表方式指定域名，详情见 域名配置 QNFixedZone；
     * SDK 自动查询域名。SDK 内部自动调用七牛服务端接口，查询 Bucket 的上传域名，详情见 域名配置 QNAutoZone；
  2. 使用上传域名进行上传，上传过程会伴随主备重试，既多个域名时，一个域名上传失败，会尝试使用其他域名进行上传。

**建议的上传域名下发方式**

用户服务在下发上传 Token 时同时下发上传域名（可以在 App 需要进行上传时，先请求获取获取上传 Token 及上传域名），可下发多个域名，App
在拿到 Token 和上传域名后，配置上传 Config 以及 QNUploadManager，进而进行上传操作。

具体代码示例如下：

    
    
    // Upload_Domain1, Upload_Domain2 为服务下发的上传域名
    QNFixedZone *fixedZone = [[QNFixedZone alloc] initWithUpDomainList:@[@"Upload_Domain1", @"Upload_Domain2"]];
    QNConfiguration *config = [QNConfiguration build:^(QNConfigurationBuilder *builder) {
        builder.zone = fixedZone;
    }];
    QNUploadManager *manager = [[QNUploadManager alloc] initWithConfiguration:config];
    

**域名下发的优点：**

  1. 跳过域名查询过程，上传更高效。
  2. 避免在 App 硬编码上传域名，导致使用不灵活，比如： 
     * 在客户更换/增加区域时，由于 App 硬编码了区域，已发布的 App 无法处理此问题。
     * 某些客户生产环境使用的 Bucket 和 测试环境使用的 Bucket 不在同一个区域，在实际上线时错用了测试 Bucket 的区域，导致 Bucket 和区域不匹配，App 相关功能不可用。
     * 自定义域名，由于硬编码，老版本 App 也无法灵活应对。

除了上面的问题，还有很多情景不再列举，上面问题的根本原因是由于 App 硬编码了区域的上传域名导致 App
不能灵活应对上传域名需要修改的场景，所以建议客户通过服务下发上传的方式来配置 SDK 的上传域名, 而不是直接硬编码上传域名。

# 3 域名配置

域名配置分为 QNFixZone 和 QNAutoZone 两种方式。

## 3.1 QNFixZone

在 QNFixZone 中，上传域名被固定，且不可更改。有两种配置方式：

### 3.1.1 通过指定上传区域 ID 方式

区域 ID 和区域域名对应关系参考 [这里 __](https://developer.qiniu.com/kodo/1671/region-
endpoint-fq)

    
    
    // 指定上传区域为 华东-浙江
    QNFixedZone *zone = [QNFixedZone createWithRegionId:@"z0"];
    

这种方式硬编码了上传域名的区域，且不可更改，所以不建议在生产环境中使用，仅供测试使用。

### 3.1.2 直接配置上传域名

直接配置上传域名的方式可以灵活配置域名，我们不建议上传域名配置为固定域名，而是通过服务下发的方式进行配置。具体上传域名下发请参考**上传域名下发** 介绍。

    
    
    // Upload_Domain1, Upload_Domain2 为服务下发的上传域名
    QNFixedZone *fixedZone = [[QNFixedZone alloc] initWithUpDomainList:@[@"Upload_Domain1", @"Upload_Domain2"]];
    

## 3.2 QNAutoZone

如果用户不想关心上传域名相关的逻辑，而且没有任何自定义的需求，完全依赖七牛的上传域名，则可以使用 AutoZone。AutoZone 相对于 FixZone
来说，在第一次上传时查询上传域名，后续会使用缓存的上传域名进行上传。在缓存有效期内不会更换上传域名，当前域名缓存有效期为 24 小时。  
示例代码：

    
    
    // 不指定 uc 域名，使用七牛公有云默认域名
    QNAutoZone *zone = [[QNAutoZone alloc] init];
    
    // 指定 uc 域名，公有云无需指定
    QNAutoZone *zone = [QNAutoZone zoneWithUcHosts:@[@"UCHost0", @"UCHost1"]];
    

不过我们推荐用户使用**上传域名下发** 的方式来配置上传域名，防止后续业务变更需要。

# 4 上传

## 4.1 上传示例

SDK 内置两种上传方式：表单上传和分片上传，并根据具体情况，内部做了自动切换。表单上传使用一个 HTTP POST
请求完成文件的上传，因此比较适合较小的文件和较好的网络环境。相比而言，分片上传更能适应不稳定的网络环境，也比较适合上传比较大的文件（例如数百 MB
或更大）。

若需深入了解上传方式之间的区别，请参阅上传类型中
[表单上传](https://developer.qiniu.com/kodo/manual/1272/form-upload) 、[分片上传 v1
版](https://developer.qiniu.com/kodo/manual/1650/chunked-upload) 和 [分片上传 v2
版](https://developer.qiniu.com/kodo/6364/multipartupload-interface) 接口说明。

QNUploadManager 上传接口参数说明：

参数 | 类型 | 说明  
---|---|---  
data | NSData */NSString */PHAsset */PHAssetResource * | 数据，可以是 NSData、文件路径、资源、数据流  
key | NSString * | 保存在服务器上的资源唯一标识，请参阅 [键值对](https://developer.qiniu.com/kodo/manual/1277/product-introduction#key-value)  
token | NSString * | 服务器分配的 token  
completionHandler | QNUpCompletionHandler | 上传回调函数，必填  
option | QNUploadOption | 如果需要进度通知、中途取消、指定 mimeType，则需要填写相应字段，详见下面的 QNUploadOption 参数说明  
  
QNUploadOption 参数说明：

参数 | 类型 | 说明  
---|---|---  
params | NSDictionary<NSString *, NSString *> * | 自定义变量，key 必须以 x: 开始  
metaDataParam | NSDictionary<NSString *, NSString *> * | 自定义meta数据，key 必须以 x-qn-meta- 开始  
mimeType | NSString | 指定文件的 mimeType  
progressHandler | QNUpProgressHandler | 上传进度回调  
      
    
    #import <QiniuSDK.h>
    
    QNConfiguration *configuration = [QNConfiguration build:^(QNConfigurationBuilder *builder) {
        // 配置上传区域，Host0、Host1 建议通过服务方式下发
        builder.zone = [[QNFixedZone alloc] initWithUpDomainList:@[@"Host0", @"Host2"]];
        // 分片上传阈值：4MB，大于 4MB 采用分片上传，小于 4MB 采用表单上传
        builder.putThreshold = 4*1024*1024;
        // 开启并发分片上传
        builder.useConcurrentResumeUpload = true;
        // 使用分片 V2
        builder.resumeUploadVersion = QNResumeUploadVersionV2;
        // 文件分片上传时断点续传信息保存，表单上传此配置无效
        NSString *recorderPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
        builder.recorder = [QNFileRecorder fileRecorderWithFolder:recorderPath error:nil];
    }];
    QNUploadManager *upManager = [[QNUploadManager alloc] initWithConfiguration:configuration];
    
    __weak typeof(self) weakSelf = self;
    QNUploadOption *uploadOption = [[QNUploadOption alloc] initWithMime:nil progressHandler:^(NSString *key, float percent) {
        NSLog(@"percent == %.2f", percent);
    }
                                                                 params:nil
                                                               checkCrc:NO
                                                     cancellationSignal:^BOOL{
        // 当需要取消时，此处返回 true，SDK 内部会多次检查返回值，当返回值为 true 时会取消上传操作
        return false;
    }];
    
    NSString *filePath = @"";    // 文件路径
    NSString *key = @"";         // 文件 key
    NSString *uploadToken = @""; // 上传的 Token
    [upManager putFile:filePath key:key token:uploadToken complete:^(QNResponseInfo *info, NSString *key, NSDictionary *resp) {
        if (info.isOK) {
            // 上传成功
        } else {
            // 上传失败
        }
    } option:uploadOption];
    

## 4.2 上传配置介绍

### 4.2.1 开启传输加速

默认情况下，SDK 未开启使用加速域名上传的功能，如需开启需按下面方式进行配置：

    
    
    // 1. 在七牛云存储控制台修改 Bucket 配置，域名管理 -> 开启传输加速（SDK 开启使用加速域名上传的功能仅仅是 SDK 支持
    //    使用加速域名，所以要想使用传输加速，七牛云服务端需开启此功能）
    // 
    // 2. SDK 配置 
    // 方式一：使用 QNFixZone 配置
    QNConfiguration *config = [QNConfiguration build:^(QNConfigurationBuilder *builder) {
        // Upload_Domain1 和 Upload_Domain2 为加速域名，可以参考七牛云存储控制台域名管理页面，建议通过用户服务下发，不要硬编码
        builder.zone =  [[QNFixedZone alloc] initWithUpDomainList:@[@"Upload_Domain1", @"Upload_Domain2"]];
    }];
    
    // 方式二：使用 AutoZone（v8.8.0 开始支持）
    QNConfiguration *config = [QNConfiguration build:^(QNConfigurationBuilder *builder) {
        builder.accelerateUploading = YES;        // 开启传输加速，此参数仅对使用 QNAutoZone 时有效
        builder.zone = [[QNAutoZone alloc] init]; // 默认是 AutoZone，所以 zone 也可以不配置
    }];
    

### 4.2.2 其他配置

    
    
    QNConfiguration *configuration = [QNConfiguration build:^(QNConfigurationBuilder *builder) {
        builder.zone = [[QNAutoZone alloc] init]; // 配置上传区域，使用 QNAutoZone
        builder.recorderKeyGen = ^NSString *(NSString *uploadKey, NSString *filePath) {
            // 自定义 文件分片上传时断点续传信息保存的 key，默认使用 uploadKey
            return [NSString stringWithFormat:@"%@-%@", uploadKey, filePath];
        };
        // 文件分片上传时断点续传信息保存，表单上传此配置无效
        NSString *recorderPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
        builder.recorder = [QNFileRecorder fileRecorderWithFolder:recorderPath error:nil];
        // 文件采用分片上传时，分片大小为 2MB
        builder.chunkSize = 2*1024*1024;
        
        // 分片上传阈值：4MB，大于 4MB 采用分片上传，小于 4MB 采用表单上传
        builder.putThreshold = 4*1024*1024;
        
        // 单个域名/IP请求失败后最大重试次数为 1 次
        builder.retryMax = 1;
        
        // 重试时间间隔：0.5s
        builder.retryInterval = 0.5;
        
        // 请求超时时间：60s
        builder.timeoutInterval = 60;
        
        // 使用 HTTPS
        builder.useHttps = true;
        
        // 使用备用域名进行重试
        builder.allowBackupHost = true;
        
        // 开启加速上传
        builder.accelerateUploading = true;
       
        // 开启并发分片上传
        builder.useConcurrentResumeUpload = true;
        
        // 使用并发分片上传时，一个文件并发上传的分片个数
        builder.concurrentTaskCount = 2;
        
        // 使用分片 V2
        builder.resumeUploadVersion = QNResumeUploadVersionV2;
    }];
    
    
    // 指定文件 mime type
    NSString *mimeType = @"";
    // 用于服务器上传回调通知的自定义参数，参数的key必须以x: 开头  eg: x:foo
    NSDictionary <NSString *, NSString *> * params = @{};
    // 用于设置meta数据，参数的key必须以x-qn-meta- 开头  eg: x-qn-meta-key
    NSDictionary <NSString *, NSString *> * metaDataParams = @{};
    BOOL checkCrc = true;
    QNUploadOption *option = [[QNUploadOption alloc] initWithMime:mimeType
                                              byteProgressHandler:^(NSString *key, long long uploadBytes, long long totalBytes) {
        // 处理上传进度
    } params:params metaDataParams:metaDataParams checkCrc:checkCrc cancellationSignal:^BOOL{
        // 当需要取消时，此处返回 false，SDK 内部会不间断检测此返回值
        return false;
    }];
    
    // 关闭 DNS 预解析
    //从 7.4.0 开始增加了 DNS 预解析和缓存策略（每 2 分钟（进程非挂起状态）会自动刷新缓存策略）来减少 DNS 解析错误。默认预解析开启，需获取 IP 信息。
    kQNGlobalConfiguration.isDnsOpen = NO;
    
    // 关闭网络状态检测，当因网络异常而失败时，会检测网络状态，进而根据情况调整重试逻辑。默认开启网络状态检测。
    kQNGlobalConfiguration.connectCheckEnable = NO;
    

# 5 下载文件

该 SDK 并未提供下载文件相关的功能接口，因为文件下载是一个标准的 HTTP GET 过程。开发者只需理解资源 URI 的组成格式即可非常方便的构建资源
URI，并在必要的时候加上 [下载凭证](https://developer.qiniu.com/kodo/manual/1202/download-
token) ，即可使用 HTTP GET 请求获取相应资源。

从安全性和代码可维护性的角度考虑，我们建议下载 URL 的拼接过程也在业务服务器进行，让客户端从业务服务器请求。

# API 参考

  * [存储 API 参考](https://developer.qiniu.com/kodo/api/3939/overview-of-the-api)
  * [官方数据处理 API 参考](https://developer.qiniu.com/dora)

# 常见问题

  * 如果碰到 crc 链接错误，请把 libz.dylib 加入到项目中去。
  * 如果碰到 res_9_ninit 链接错误，请把 libresolv.dylib 加入到项目中去。
  * 如果需要支持 iOS 5 或者支持 RestKit，请用 AFNetworking 1.x 分支的版本。
  * 如果碰到其他编译错误，请参考 Cocoapods 的[troubleshooting __](http://guides.cocoapods.org/using/troubleshooting.html)。
  * iOS 9+ 强制使用 https ，需要在 project build info 添加 NSAppTransportSecurity 类型 Dictionary。在 NSAppTransportSecurity下添加 NSAllowsArbitraryLoads 类型 Boolean ，值设为 YES。具体操作请查阅[这里 __](http://blog.csdn.net/guoer9973/article/details/48622823)。

# 相关资源

如果您有任何关于我们文档或产品的建议和想法，欢迎您通过以下方式与我们互动讨论：

  * [技术论坛 __](http://segmentfault.com/qiniu)\- 在这里您可以和其他开发者愉快的讨论如何更好的使用七牛云服务
  * [提交工单 __](http://support.qiniu.com/)\- 如果您的问题不适合在论坛讨论或希望及时解决，您也可以提交一个工单，我们的技术支持人员会第一时间回复您
  * [博客 __](http://blog.qiniu.com)\- 这里会持续更新发布市场活动和技术分享文章
  * [微博 __](http://weibo.com/qiniutek)
  * [常见问题 __](https://support.qiniu.com/)

# 贡献代码

  1. Fork

  2. 创建您的特性分支 git checkout -b my-new-feature

  3. 提交您的改动 git commit -am ‘Added some feature’

  4. 将您的修改记录提交到远程 git 仓库 git push origin my-new-feature

  5. 然后到 github 网站的该 git 远程仓库的 my-new-feature 分支下发起 Pull Request

# 许可证

Copyright © 2020 qiniu.com

基于 MIT 协议发布:

  * [www.opensource.org/licenses/MIT __](http://www.opensource.org/licenses/MIT)

以上内容是否对您有帮助？