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

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

Note

本指南主要面向适用于 C++ 的 Azure 存储客户端库 1.0.0 版及更高版本。 建议使用最新版本的用于 C++ 的存储客户端库(通过 NuGetGitHub 提供)。

什么是 Blob 存储?

Azure Blob 存储是 Azure 的适用于云的对象存储解决方案。 Blob 存储最适合存储巨量的非结构化数据,例如文本或二进制数据。

Blob 存储最适合用于:

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

可以通过 HTTP 或 HTTPS 从世界上的任何位置访问 Blob 存储中的对象。 用户或客户端应用程序可以通过 URL、Azure 存储 REST APIAzure PowerShellAzure CLI 或 Azure 存储客户端库访问 Blob。 存储客户端库以多种语言提供,包括 .NETJavaNode.jsPythonPHPRuby

Blob 服务概念

Blob 存储公开了三种资源:存储帐户、帐户中的容器,以及容器中的 blob。 以下图示显示了这些资源之间的关系。

Blob(对象)存储体系结构的图示

存储帐户

对 Azure 存储中所有数据对象的访问都是通过存储帐户进行的。 有关详细信息,请参阅关于 Azure 存储帐户

容器

容器对一组 blob 进行组织,类似于文件系统中的文件夹。 所有 Blob 都驻留在容器中。 一个存储帐户可以包含无限数量的容器,一个容器可以存储无限数量的 Blob。 请注意,容器名称必须小写。

Blob

Azure 存储提供三种类型的 Blob:块 Blob、追加 Blob 和页 Blob(用于 VHD 文件)。

  • 块 Blob 存储文本和二进制数据,最多约为 4.7 TB。 块 Blob 由可以分别管理的数据块构成。
  • 与块 Blob 一样,追加 Blob 也由块构成,但针对追加操作进行了优化。 追加 Blob 非常适用于诸如记录来自虚拟机的数据之类的场景。
  • 页 Blob 用于存储最大 8 TB 的随机访问文件。 页 Blob 存储着为 VM 提供支撑的 VHD 文件。

所有 Blob 都驻留在容器中。 容器类似于文件系统中的文件夹。 你可以进一步将 Blob 组织到虚拟目录中,并遍历它们,就像对待文件系统一样。

如果使用的是极大型数据集,并且因网络限制而无法通过网络向 Blob 存储上传数据或从其下载数据,则可将一组硬盘驱动器寄送给我们,以便直接通过数据中心导入或导出数据。 有关详细信息,请参阅使用 Azure 导入/导出服务将数据传输到 Blob 存储

有关命名容器和 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>
#include <cpprest/filestream.h>  
#include <cpprest/containerstream.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 存储的详细信息。