如何通过 iOS 使用 Blob 存储

本文演示如何使用 Microsoft Azure Blob 存储执行常见任务。 示例采用 Objective-C 编写,并使用了适用于 iOS 的 Azure 存储客户端库。 涉及的任务包括上传、列出、下载和删除 Blob。 有关 Blob 的详细信息,请参阅后续步骤部分。 也可下载示例应用,快速了解如何在 iOS 应用程序中使用 Azure 存储。

若要了解有关 Blob 存储的详细信息,请参阅 Azure Blob 存储简介

创建 Azure 存储帐户

创建第一个 Azure 存储帐户的最简单方法是使用 Azure 门户。 若要了解更多信息,请参阅 创建存储帐户

还可使用 Azure PowerShellAzure CLI适用于 .NET 的 Azure 存储资源提供程序创建 Azure 存储帐户。

如果暂时不想在 Azure 中创建存储帐户,也可以使用 Azurite 存储模拟器在本地环境中运行和测试代码。 有关详细信息,请参阅使用 Azurite 模拟器进行本地 Azure 存储开发

将 Azure 存储空间 iOS 库导入到应用程序中

可使用 Azure 存储 CocoaPod 或导入 Framework 文件,将 Azure 存储 iOS 库导入到应用程序。 CocoaPod 是建议的方法,因为它可使集成库更轻松,但是从现有项目的框架文件导入更少侵入性。

若要使用此库,需要以下项:

  • iOS 8+
  • Xcode 7+

CocoaPod

  1. 如果尚未这样做,请打开终端窗口并运行以下命令,在计算机上安装 CocoaPods

    sudo gem install cocoapods
    
  2. 接下来,在项目目录(包含 .xcodeproj 文件的目录)中创建名为 Podfile 的文件(无扩展名)。 将以下内容添加到 Podfile 并保存。

    platform :ios, '8.0'
    
    target 'TargetName' do
      pod 'AZSClient'
    end
    
  3. 在终端窗口中,导航到项目目录并运行以下命令

    pod install
    
  4. 如果已在 Xcode 中打开 .xcodeproj,请将其关闭。 在项目目录中打开新建的项目文件(扩展名为 .xcworkspace)。 从现在开始将使用此文件。

框架

使用库的其他方法是手动生成框架:

  1. 首先,下载或克隆 azure-storage-ios repo
  2. 转到“azure-storage-ios”->“Lib”->“Azure 存储客户端库”,并在 Xcode 中打开 AZSClient.xcodeproj
  3. 在 Xcode 的左上方,将活动方案从“Azure 存储客户端库”更改为“Framework”。
  4. 生成项目 (⌘+B)。 这会在桌面上创建 AZSClient.framework 文件。

可以通过执行以操作将框架文件导入到应用程序:

  1. 在 Xcode 中创建一个新项目或打开现有项目。
  2. AZSClient.framework 拖放到 Xcode 项目导航器中。
  3. 选择“需要时复制项”,并单击“完成”。
  4. 单击左侧导航栏中的项目,并在项目编辑器顶部,单击“常规”选项卡。
  5. 在“链接的框架和库”部分下,单击“添加”按钮 (+)。
  6. 在已提供的库的列表中,搜索 libxml2.2.tbd 并将其添加到项目。

导入该库

// Include the following import statement to use blob APIs.
#import <AZSClient/AZSClient.h>

如果使用 Swift,则需要创建桥接头并在该位置导入 <AZSClient/AZSClient.h>:

  1. 创建头文件 Bridging-Header.h,并添加上面的 import 语句。
  2. 转到“生成设置”选项卡,并搜索“Objective-C 桥接头文件”。
  3. 双击“Objective-C 桥接头文件”字段并添加头文件的路径:ProjectName/Bridging-Header.h
  4. 生成项目 (⌘+B) 以确认桥接头文件已由 Xcode 选取。
  5. 开始在任何 Swift 文件中直接使用库,不需要 import 语句。

创建用于访问 Azure 存储的应用程序

有两种方法可以对要访问存储服务的应用程序进行身份验证:

  • 共享密钥:仅将共享密钥用于测试目的
  • 共享访问签名 (SAS):将 SAS 用于生产应用程序

共享密钥

共享密钥身份验证意味着应用程序将使用帐户名和帐户密钥访问存储服务。 为了快速说明如何使用此库,我们会在此入门指南中使用共享密钥身份验证。

警告

请仅将共享密钥身份验证用于测试用途! 为关联的存储帐户提供完全读/写访问权限的帐户名和帐户密钥将分发给下载应用的每个人。 这是好的做法,你会面临向不受信任的客户端泄露密钥的风险。

使用共享密钥身份验证时,将创建一个连接字符串。 连接字符串由以下部分组成:

  • DefaultEndpointsProtocol - 可以选择 HTTP 或 HTTPS。 但是,强烈建议使用 HTTPS。
  • 帐户名 - 存储帐户的名称
  • 帐户密钥 - 在 Azure 门户上,导航到存储帐户,并单击“密钥”图标以查看此信息。
  • (可选)EndpointSuffix - 用于区域中具有不同终结点后缀的存储服务,例如 Azure 中国或 Azure 调控。

以下是使用共享密钥身份验证的连接字符串示例:

"DefaultEndpointsProtocol=https;AccountName=your_account_name_here;AccountKey=your_account_key_here"

共享访问签名 (SAS)

对于移动应用程序,针对 Azure 存储服务对客户端请求进行身份验证的建议方法是使用共享访问签名 (SAS)。 SAS 允许使用指定的权限集向客户端授予在指定的时间内对资源的访问权限。 作为存储帐户所有者,需要为移动客户端生成要使用的 SAS。 要生成 SAS,可能需要编写单独的服务,该服务生成要分发给客户端的 SAS。 出于测试目的,可以使用 Microsoft Azure 存储资源管理器Azure 门户来生成 SAS。 创建 SAS 时,可以指定 SAS 有效的时间间隔,以及 SAS 授予客户端的权限。

以下示例演示如何使用 Microsoft Azure 存储资源管理器来生成 SAS。

  1. 安装 Microsoft Azure 存储资源管理器(如果尚未安装)

  2. 连接到订阅

  3. 单击存储帐户,并单击左下方的“操作”选项卡。 单击“获取共享访问签名”,生成 SAS 的连接字符串。

  4. 下面是 SAS 连接字符串的示例,该字符串为存储帐户的 Blob 服务授予对服务、容器和对象级别的读取与写入权限。

    "SharedAccessSignature=sv=2015-04-05&ss=b&srt=sco&sp=rw&se=2016-07-21T18%3A00%3A00Z&sig=3ABdLOJZosCp0o491T%2BqZGKIhafF1nlM3MzESDDD3Gg%3D;BlobEndpoint=https://youraccount.blob.core.windows.net"

可以看到,使用 SAS 时,不会在应用程序中公开帐户密钥。 可查阅共享访问签名:了解 SAS 模型,了解有关 SAS 和使用 SAS 的最佳做法的详细信息。

异步操作

注意

执行对服务的请求的所有方法都是异步操作。 在代码示例中,会发现这些方法都有完成处理程序。 请求完成,将运行完成处理程序内的代码。 正在发出请求,将运行完成处理程序后的代码。

创建容器

Azure 存储空间中的每个 Blob 都必须驻留在一个容器中。 以下示例演示如何在存储帐户中创建一个名为 newcontainer 的容器(如果它尚不存在)。 在选择容器的名称时,请注意上面提到的命名规则。

-(void)createContainer{
    NSError *accountCreationError;

    // Create a storage account object from a connection string.
    AZSCloudStorageAccount *account = [AZSCloudStorageAccount accountFromConnectionString:@"DefaultEndpointsProtocol=https;AccountName=your_account_name_here;AccountKey=your_account_key_here" error:&accountCreationError];

    if(accountCreationError){
        NSLog(@"Error in creating account.");
    }

    // Create a blob service client object.
    AZSCloudBlobClient *blobClient = [account getBlobClient];

    // Create a local container object.
    AZSCloudBlobContainer *blobContainer = [blobClient containerReferenceFromName:@"newcontainer"];

    // Create container in your Storage account if the container doesn't already exist
    [blobContainer createContainerIfNotExistsWithCompletionHandler:^(NSError *error, BOOL exists) {
        if (error){
            NSLog(@"Error in creating container.");
        }
    }];
}

可通过查看 Microsoft Azure 存储资源管理器,并验证 newcontainer 是否存在于存储帐户的容器列表中来确认此操作是否有效。

设置容器权限

默认情况下,容器的权限配置为专用访问权限。 但是,容器提供了几个不同的容器访问权限选项:

  • 专用:仅帐户所有者可以读取容器和 Blob 数据。
  • Blob:可以通过匿名请求读取此容器中的 Blob 数据,但容器数据不可用。 客户端无法通过匿名请求枚举容器中的 Blob。
  • 容器:可以通过匿名请求读取容器和 Blob 数据。 客户端可以通过匿名请求枚举容器中的 Blob,但无法枚举存储帐户中的容器。

以下示例演示如何创建一个具有容器访问权限的容器,这会允许 Internet 上的所有用户对其进行公共只读访问:

-(void)createContainerWithPublicAccess{
    NSError *accountCreationError;

    // Create a storage account object from a connection string.
    AZSCloudStorageAccount *account = [AZSCloudStorageAccount accountFromConnectionString:@"DefaultEndpointsProtocol=https;AccountName=your_account_name_here;AccountKey=your_account_key_here" error:&accountCreationError];

    if(accountCreationError){
        NSLog(@"Error in creating account.");
    }

    // Create a blob service client object.
    AZSCloudBlobClient *blobClient = [account getBlobClient];

    // Create a local container object.
    AZSCloudBlobContainer *blobContainer = [blobClient containerReferenceFromName:@"containerpublic"];

    // Create container in your Storage account if the container doesn't already exist
    [blobContainer createContainerIfNotExistsWithAccessType:AZSContainerPublicAccessTypeContainer requestOptions:nil operationContext:nil completionHandler:^(NSError *error, BOOL exists){
        if (error){
            NSLog(@"Error in creating container.");
        }
    }];
}

将 Blob 上传到容器中

如“Blob 服务概念”部分中所述,Blob 存储提供了三种不同类型的 blob:块 blob、追加 blob 和页 blob。 Azure 存储 iOS 库支持所有这三种类型的 blob。 大多数情况下,推荐使用块 Blob 类型。

以下示例演示如何从 NSString 上传块 blob。 如果此容器中已存在同名的 blob,则将覆盖该 blob 的内容。

-(void)uploadBlobToContainer{
    NSError *accountCreationError;

    // Create a storage account object from a connection string.
    AZSCloudStorageAccount *account = [AZSCloudStorageAccount accountFromConnectionString:@"DefaultEndpointsProtocol=https;AccountName=your_account_name_here;AccountKey=your_account_key_here" error:&accountCreationError];

    if(accountCreationError){
        NSLog(@"Error in creating account.");
    }

    // Create a blob service client object.
    AZSCloudBlobClient *blobClient = [account getBlobClient];

    // Create a local container object.
    AZSCloudBlobContainer *blobContainer = [blobClient containerReferenceFromName:@"containerpublic"];

    [blobContainer createContainerIfNotExistsWithAccessType:AZSContainerPublicAccessTypeContainer requestOptions:nil operationContext:nil completionHandler:^(NSError *error, BOOL exists)
        {
            if (error){
                NSLog(@"Error in creating container.");
            }
            else{
                // Create a local blob object
                AZSCloudBlockBlob *blockBlob = [blobContainer blockBlobReferenceFromName:@"sampleblob"];

                // Upload blob to Storage
                [blockBlob uploadFromText:@"This text will be uploaded to Blob Storage." completionHandler:^(NSError *error) {
                    if (error){
                        NSLog(@"Error in creating blob.");
                    }
                }];
            }
        }];
}

可通过查看 Microsoft Azure 存储资源管理器并验证容器 containerpublic 是否包含该 Blob sampleblob 来确认此操作是否正常工作。 在此示例中,我们使用了公共容器,因此还可以通过转到 blob URI 来验证此应用程序是否正常工作:

https://nameofyourstorageaccount.blob.core.windows.net/containerpublic/sampleblob

除了从 NSString 上传块 blob 外,NSData、NSInputStream 或本地文件也存在类似的方法。

列出容器中的 Blob

以下示例演示如何列出容器中的所有 blob。 执行此操作时,应注意以下参数:

  • continuationToken - 继续标记表示列出操作应开始的位置。 如果未提供标记,它将从开头列出 blob。 可以列出任意数目的 blob,从零到最大集。 即使此方法返回零个结果,如果 results.continuationToken 不为空,则服务中也可能存在更多 blob 未列出。
  • prefix - 可以指定要用于 blob 列出的前缀。 将仅列出以该前缀开头的 blob。
  • useFlatBlobListing - 如命名和引用容器和 blob 部分中所述,虽然 Blob 服务是平面存储方案,但可通过命名具有路径信息的 blob 来创建虚拟层次结构。 但是,目前不支持非平面列表。 此功能即将支持。 目前,此值应为 YES
  • blobListingDetails - 可指定在列出 blob 时要包含哪些项
    • AZSBlobListingDetailsNone:仅列出已提交的 blob,并且不返回 blob 元数据。
    • AZSBlobListingDetailsSnapshots:列出提交的 blob 和 blob 快照。
    • AZSBlobListingDetailsMetadata:检索列表中返回的每个 blob 的 blob 元数据。
    • AZSBlobListingDetailsUncommittedBlobs:列出已提交和未提交的 blob。
    • AZSBlobListingDetailsCopy:在列表中包含复制属性。
    • AZSBlobListingDetailsAll:列出所有可用的已提交 blob、未提交 blob 和快照,并返回这些 blob 的所有元数据和复制状态。
  • maxResults - 此操作可返回的结果的最大数目。 使用 -1 以不设置限制。
  • completionHandler - 要使用列表操作的结果执行的代码块。

在此示例中,帮助器方法用于在每次返回继续标记时递归调用列出 blob 方法。

-(void)listBlobsInContainer{
    NSError *accountCreationError;

    // Create a storage account object from a connection string.
    AZSCloudStorageAccount *account = [AZSCloudStorageAccount accountFromConnectionString:@"DefaultEndpointsProtocol=https;AccountName=your_account_name_here;AccountKey=your_account_key_here" error:&accountCreationError];

    if(accountCreationError){
        NSLog(@"Error in creating account.");
    }

    // Create a blob service client object.
    AZSCloudBlobClient *blobClient = [account getBlobClient];

    // Create a local container object.
    AZSCloudBlobContainer *blobContainer = [blobClient containerReferenceFromName:@"containerpublic"];

    //List all blobs in container
    [self listBlobsInContainerHelper:blobContainer continuationToken:nil prefix:nil blobListingDetails:AZSBlobListingDetailsAll maxResults:-1 completionHandler:^(NSError *error) {
        if (error != nil){
            NSLog(@"Error in creating container.");
        }
    }];
}

//List blobs helper method
-(void)listBlobsInContainerHelper:(AZSCloudBlobContainer *)container continuationToken:(AZSContinuationToken *)continuationToken prefix:(NSString *)prefix blobListingDetails:(AZSBlobListingDetails)blobListingDetails maxResults:(NSUInteger)maxResults completionHandler:(void (^)(NSError *))completionHandler
{
    [container listBlobsSegmentedWithContinuationToken:continuationToken prefix:prefix useFlatBlobListing:YES blobListingDetails:blobListingDetails maxResults:maxResults completionHandler:^(NSError *error, AZSBlobResultSegment *results) {
        if (error)
        {
            completionHandler(error);
        }
        else
        {
            for (int i = 0; i < results.blobs.count; i++) {
                NSLog(@"%@",[(AZSCloudBlockBlob *)results.blobs[i] blobName]);
            }
            if (results.continuationToken)
            {
                [self listBlobsInContainerHelper:container continuationToken:results.continuationToken prefix:prefix blobListingDetails:blobListingDetails maxResults:maxResults completionHandler:completionHandler];
            }
            else
            {
                completionHandler(nil);
            }
        }
    }];
}

下载 Blob

以下示例演示如何将 blob 下载到 NSString 对象中。

-(void)downloadBlobToString{
    NSError *accountCreationError;

    // Create a storage account object from a connection string.
    AZSCloudStorageAccount *account = [AZSCloudStorageAccount accountFromConnectionString:@"DefaultEndpointsProtocol=https;AccountName=your_account_name_here;AccountKey=your_account_key_here" error:&accountCreationError];

    if(accountCreationError){
        NSLog(@"Error in creating account.");
    }

    // Create a blob service client object.
    AZSCloudBlobClient *blobClient = [account getBlobClient];

    // Create a local container object.
    AZSCloudBlobContainer *blobContainer = [blobClient containerReferenceFromName:@"containerpublic"];

    // Create a local blob object
    AZSCloudBlockBlob *blockBlob = [blobContainer blockBlobReferenceFromName:@"sampleblob"];

    // Download blob
    [blockBlob downloadToTextWithCompletionHandler:^(NSError *error, NSString *text) {
        if (error) {
            NSLog(@"Error in downloading blob");
        }
        else{
            NSLog(@"%@",text);
        }
    }];
}

删除 Blob

以下示例说明如何删除 blob。

-(void)deleteBlob{
    NSError *accountCreationError;

    // Create a storage account object from a connection string.
    AZSCloudStorageAccount *account = [AZSCloudStorageAccount accountFromConnectionString:@"DefaultEndpointsProtocol=https;AccountName=your_account_name_here;AccountKey=your_account_key_here" error:&accountCreationError];

    if(accountCreationError){
        NSLog(@"Error in creating account.");
    }

    // Create a blob service client object.
    AZSCloudBlobClient *blobClient = [account getBlobClient];

    // Create a local container object.
    AZSCloudBlobContainer *blobContainer = [blobClient containerReferenceFromName:@"containerpublic"];

    // Create a local blob object
    AZSCloudBlockBlob *blockBlob = [blobContainer blockBlobReferenceFromName:@"sampleblob1"];

    // Delete blob
    [blockBlob deleteWithCompletionHandler:^(NSError *error) {
        if (error) {
            NSLog(@"Error in deleting blob.");
        }
    }];
}

删除 Blob 容器

以下示例说明如何删除容器。

-(void)deleteContainer{
    NSError *accountCreationError;

    // Create a storage account object from a connection string.
    AZSCloudStorageAccount *account = [AZSCloudStorageAccount accountFromConnectionString:@"DefaultEndpointsProtocol=https;AccountName=your_account_name_here;AccountKey=your_account_key_here" error:&accountCreationError];

    if(accountCreationError){
        NSLog(@"Error in creating account.");
    }

    // Create a blob service client object.
    AZSCloudBlobClient *blobClient = [account getBlobClient];

    // Create a local container object.
    AZSCloudBlobContainer *blobContainer = [blobClient containerReferenceFromName:@"containerpublic"];

    // Delete container
    [blobContainer deleteContainerIfExistsWithCompletionHandler:^(NSError *error, BOOL success) {
        if(error){
            NSLog(@"Error in deleting container");
        }
    }];
}

后续步骤

了解如何从 iOS 使用 Blob 存储后,请单击以下链接详细了解 iOS 库和存储服务。

如果对此库有任何疑问,可随时在 Microsoft 问答问题页面Stack Overflow 中提问。 如果有关于 Azure 存储的功能建议,请将建议发布到 Azure 存储反馈