如何通过 C++ 使用 Blob 存储

Tip

使用 Microsoft Azure 存储资源管理器管理 Azure Blob 存储资源

Microsoft Azure 存储资源管理器 是 Microsoft 免费提供的独立应用,可用于管理 Azure Blob 存储资源。 使用 Microsoft Azure 存储资源管理器可以直观地创建、读取、更新和删除 Blob 容器与 Blob,以及管理对 Blob 容器和 Blob 的访问。

概述

Azure Blob 存储是一种将非结构化数据作为对象/Blob 存储在云中的服务。 Blob 存储可以存储任何类型的文本或二进制数据,例如文档、媒体文件或应用程序安装程序。 Blob 存储也称为对象存储。

本指南将演示如何使用 Azure Blob 存储服务执行常见方案。 示例采用 C++ 编写,并使用了适用于 C++ 的 Azure 存储客户端库。 涉及的任务包括上传、列出、下载和删除 Blob。

Note

本指南主要面向适用于 C++ 的 Azure 存储客户端库 1.0.0 版及更高版本。 推荐版本:存储客户端库 2.2.0(可通过 NuGetGitHub 获得)。

什么是 Blob 存储

Azure Blob 存储是用于存储大量非结构化对象数据(例如文本或二进制数据)的服务,这些数据可通过 HTTP 或 HTTPS 从世界各地进行访问。 可以使用 Blob 存储向外公开数据,或者私下存储应用程序数据。

Blob 存储的常见用途包括:

  • 直接向浏览器提供图像或文档
  • 存储文件以供分布式访问
  • 对视频和音频进行流式处理
  • 存储数据以用于备份和还原、灾难恢复及存档
  • 存储数据以供本地或 Azure 托管服务执行分析

Blob 服务概念

Blob 服务包含以下组件:

Blob 体系结构

  • 存储帐户: 对 Azure 存储服务的所有访问都要通过存储帐户来完成。 此存储帐户可以是常规用途存储帐户,也可以是专用于存储对象/Blob 的 Blob 存储帐户。 有关详细信息,请参阅关于 Azure 存储帐户
  • 容器: 一个容器包含一组 blob 集。 所有 blob 必须位于相应的容器中。 一个帐户可以包含无限个容器。 一个容器可以存储无限个 Blob。 请注意,容器名称必须小写。
  • Blob: 任何类型和大小的文件。 Azure 存储提供三种类型的 Blob:块 Blob、页 Blob 和追加 Blob。

    块 Blob 特别适用于存储短的文本或二进制文件,例如文档和媒体文件。 追加 Blob 类似于块 Blob,因为它们是由块组成的,但针对追加操作对它们进行了优化,因此它们适用于日志记录方案。 单个块 Blob 可以包含最多 50000 个块,每个块最大 100 MB,总大小稍微大于 4.75 TB (100 MB X 50000)。 单个追加 Blob 可以包含最多 50000 个块,每个块最大 4 MB,总大小稍微大于 195 GB (4 MB X 50000)。

    页 Blob 最大可达 1 TB 大小,并且对于频繁的读/写操作更加高效。 Azure 虚拟机使用页 Blob 作为 OS 和数据磁盘。

    有关命名容器和 Blob 的详细信息,请参阅 命名和引用容器、Blob 和元数据

创建 Azure 存储帐户

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

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

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

创建 C++ 应用程序

本指南会使用存储功能,这些功能可以在 C++ 应用程序中运行。

为此,需要安装适用于 C++ 的 Azure 存储客户端库,并在 Azure 订阅中创建 Azure 存储帐户。

若要安装适用于 C++ 的 Azure 存储客户端库,可使用以下方法:

配置应用程序以访问 Blob 存储

将以下 include 语句添加到 C++ 文件的顶部,要在此使用 Azure 存储 API 来访问 blob:

#include <was/storage_account.h>
#include <was/blob.h>

设置 Azure 存储连接字符串

Azure 存储客户端使用存储连接字符串来存储用于访问数据管理服务的终结点和凭据。 在客户端应用程序中运行时,必须提供以下格式的存储连接字符串,并对 AccountName 和 AccountKey 值使用 Azure 门户中列出的存储帐户的名称和存储帐户的存储访问密钥。 有关存储帐户和访问密钥的信息,请参阅关于 Azure 存储帐户。 此示例演示如何声明一个静态字段以保存连接字符串:

// Define the connection-string with your values.
const utility::string_t storage_connection_string(U("DefaultEndpointsProtocol=https;AccountName=your_storage_account;AccountKey=your_storage_account_key;EndpointSuffix=core.chinacloudapi.cn"));

若要在本地 Windows 计算机中测试应用程序,可以使用随 Azure SDK 一起安装的 Azure 存储模拟器。 存储模拟器是一种用于模拟本地开发计算机上 Azure 中可用的 Blob、队列和表服务的实用程序。 以下示例演示如何声明一个静态字段以将连接字符串保存到本地存储模拟器:

// Define the connection-string with Azure Storage Emulator.
const utility::string_t storage_connection_string(U("UseDevelopmentStorage=true;"));  

若要启动 Azure 存储模拟器,请选择“开始”按钮或按 Windows 键。 开始键入“Azure 存储模拟器”,并从应用程序列表中选择“Azure 存储模拟器”。

下面的示例假定使用了这两个方法之一来获取存储连接字符串。

检索连接字符串

可使用 cloud_storage_account 类来表示存储帐户信息。 若要从存储连接字符串中检索存储帐户信息,可以使用 parse 方法。

// Retrieve storage account from connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

其次,获取对 cloud_blob_client 类的引用,因为它允许用户检索表示存储在 Blob 存储服务中的容器和 Blob 的对象。 以下代码使用我们在上面检索到的存储帐户对象创建 cloud_blob_client 对象:

// Create the blob client.
azure::storage::cloud_blob_client blob_client = storage_account.create_cloud_blob_client();  

如何:创建容器

Azure 存储中的每个 Blob 必须驻留在一个容器中。 该容器构成 Blob 名称的一部分。 例如,在这些示例 Blob URI 中,mycontainer 是容器的名称:

https://storagesample.blob.core.chinacloudapi.cn/mycontainer/blob1.txt
https://storagesample.blob.core.chinacloudapi.cn/mycontainer/photos/myphoto.jpg

容器名称必须是有效的 DNS 名称,并符合以下命名规则:

  1. 容器名称必须以字母或数字开头,并且只能包含字母、数字和短划线 (-) 字符。
  2. 每个短划线 (-) 字符的前面和后面都必须是一个字母或数字;在容器名称中不允许连续的短划线 (-)。
  3. 容器名称中的所有字母都必须为小写。
  4. 容器名称必须介于 3 到 63 个字符。

Important

请注意,容器的名称必须始终为小写。 如果你在容器名称中包括大写字母或以其他方式违反了容器命名规则,则可能会收到 400 错误(错误请求)。

此示例演示如何创建一个容器(如果该容器不存在):

try
{
    // Retrieve storage account from connection string.
    azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

    // Create the blob client.
    azure::storage::cloud_blob_client blob_client = storage_account.create_cloud_blob_client();

    // Retrieve a reference to a container.
    azure::storage::cloud_blob_container container = blob_client.get_container_reference(U("my-sample-container"));

    // Create the container if it doesn't already exist.
    container.create_if_not_exists();
}
catch (const std::exception& e)
{
    std::wcout << U("Error: ") << e.what() << std::endl;
}  

默认情况下,新容器是专用容器,因此,必须指定存储访问密钥才能从该容器下载 Blob。 如果要使容器中的文件 (Blob) 对任何人都可用,则可以使用以下代码将容器设置为公用:

// Make the blob container publicly accessible.
azure::storage::blob_container_permissions permissions;
permissions.set_public_access(azure::storage::blob_container_public_access_type::blob);
container.upload_permissions(permissions);  

Internet 中的所有人都可以查看公共容器中的 Blob,但是,仅在具有相应的访问密钥时,才能修改或删除它们。

如何:将 Blob 上传到容器

Azure Blob 存储支持块 Blob 和页 Blob。 大多数情况下,推荐使用块 Blob。

要将文件上传到块 Blob,请获取容器引用,并使用它获取块 Blob 引用。 获取 Blob 引用后,可以通过调用 upload_from_stream 方法将任何数据流上传到其中。 如果之前不存在 Blob,此操作会创建一个;如果存在 Blob,此操作将覆盖它。 下面的示例演示了如何将 Blob 上传到容器中,并假定已创建容器。

// Retrieve storage account from connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

// Create the blob client.
azure::storage::cloud_blob_client blob_client = storage_account.create_cloud_blob_client();

// Retrieve a reference to a previously created container.
azure::storage::cloud_blob_container container = blob_client.get_container_reference(U("my-sample-container"));

// Retrieve reference to a blob named "my-blob-1".
azure::storage::cloud_block_blob blockBlob = container.get_block_blob_reference(U("my-blob-1"));

// Create or overwrite the "my-blob-1" blob with contents from a local file.
concurrency::streams::istream input_stream = concurrency::streams::file_stream<uint8_t>::open_istream(U("DataFile.txt")).get();
blockBlob.upload_from_stream(input_stream);
input_stream.close().wait();

// Create or overwrite the "my-blob-2" and "my-blob-3" blobs with contents from text.
// Retrieve a reference to a blob named "my-blob-2".
azure::storage::cloud_block_blob blob2 = container.get_block_blob_reference(U("my-blob-2"));
blob2.upload_text(U("more text"));

// Retrieve a reference to a blob named "my-blob-3".
azure::storage::cloud_block_blob blob3 = container.get_block_blob_reference(U("my-directory/my-sub-directory/my-blob-3"));
blob3.upload_text(U("other text"));  

还可以使用 upload_from_file 方法将文件上传到块 Blob。

如何:列出容器中的 Blob

若要列出容器中的 Blob,首先需要获取容器引用。 然后,可以使用容器的 list_blobs 方法来检索其中的 Blob 和/或目录。 若要针对一个返回的 list_blob_item 访问其丰富的属性和方法,必须调用 list_blob_item.as_blob 方法以获取一个 cloud_blob 对象,或调用 list_blob.as_directory 方法以获取 cloud_blob_directory 对象。 以下代码演示如何检索和输出 my-sample-container 容器中每一项的 URI:

// Retrieve storage account from connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

// Create the blob client.
azure::storage::cloud_blob_client blob_client = storage_account.create_cloud_blob_client();

// Retrieve a reference to a previously created container.
azure::storage::cloud_blob_container container = blob_client.get_container_reference(U("my-sample-container"));

// Output URI of each item.
azure::storage::list_blob_item_iterator end_of_results;
for (auto it = container.list_blobs(); it != end_of_results; ++it)
{
    if (it->is_blob())
    {
        std::wcout << U("Blob: ") << it->as_blob().uri().primary_uri().to_string() << std::endl;
    }
    else
    {
        std::wcout << U("Directory: ") << it->as_directory().uri().primary_uri().to_string() << std::endl;
    }
}

有关列出操作的更多详细信息,请参阅使用 C++ 列出 Azure 存储资源

如何:下载 Blob

如果要下载 Blob,请首先检索 Blob 引用,然后调用 download_to_stream 方法。 以下示例使用 download_to_stream 方法将 Blob 内容传输到一个流对象,用户即可将该对象保存到本地文件。

// Retrieve storage account from connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

// Create the blob client.
azure::storage::cloud_blob_client blob_client = storage_account.create_cloud_blob_client();

// Retrieve a reference to a previously created container.
azure::storage::cloud_blob_container container = blob_client.get_container_reference(U("my-sample-container"));

// Retrieve reference to a blob named "my-blob-1".
azure::storage::cloud_block_blob blockBlob = container.get_block_blob_reference(U("my-blob-1"));

// Save blob contents to a file.
concurrency::streams::container_buffer<std::vector<uint8_t>> buffer;
concurrency::streams::ostream output_stream(buffer);
blockBlob.download_to_stream(output_stream);

std::ofstream outfile("DownloadBlobFile.txt", std::ofstream::binary);
std::vector<unsigned char>& data = buffer.collection();

outfile.write((char *)&data[0], buffer.size());
outfile.close();  

也可以使用 download_to_file 方法将 Blob 的内容下载到文件。 此外,还可以使用 download_text 方法以文本字符串形式下载 Blob 的内容。

// Retrieve storage account from connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

// Create the blob client.
azure::storage::cloud_blob_client blob_client = storage_account.create_cloud_blob_client();

// Retrieve a reference to a previously created container.
azure::storage::cloud_blob_container container = blob_client.get_container_reference(U("my-sample-container"));

// Retrieve reference to a blob named "my-blob-2".
azure::storage::cloud_block_blob text_blob = container.get_block_blob_reference(U("my-blob-2"));

// Download the contents of a blog as a text string.
utility::string_t text = text_blob.download_text();

如何:删除 Blob

如果要删除 Blob,请先获取 Blob 引用,然后对其调用 delete_blob 方法。

// Retrieve storage account from connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

// Create the blob client.
azure::storage::cloud_blob_client blob_client = storage_account.create_cloud_blob_client();

// Retrieve a reference to a previously created container.
azure::storage::cloud_blob_container container = blob_client.get_container_reference(U("my-sample-container"));

// Retrieve reference to a blob named "my-blob-1".
azure::storage::cloud_block_blob blockBlob = container.get_block_blob_reference(U("my-blob-1"));

// Delete the blob.
blockBlob.delete_blob();

后续步骤

既然已了解 blob 存储的基础知识,请打开以下链接了解有关 Azure 存储的详细信息。