在 pageblob 与 blockblob 中下载 blob

Downloading of blob in pageblob vs blockblob

如有错误请指正。 PageBlob 和 BlockBlob 的下载是一样的,而写操作是不同的吗?我假设下载是相同的,因为如果我们有一个 blob URI,我们可以只使用 GET 来下载 blob。 最后,是否有文档支持我的假设,即无论 blob 的类型如何,两者下载的 blob 都是相同的。

通常 Pageblob 很大,它们充当虚拟机的卷。

“页面 blob 由 512 字节的页面组成,总大小高达 8 TB,专为频繁随机 read/write 操作而设计。”

Microsoft documentation 以了解有关页面 Blob 的更多信息。

Azure 存储中将存在三种不同类型的 blob,Page、Append、Blob。

下面的 Python 代码将帮助我们将 blob 下载到本地存储。

import logging
import os
import azure.functions as func
from azure.storage.blob import BlobServiceClient, BlobClient
from azure.storage.blob import ContentSettings, ContainerClient

logging.info('Python HTTP trigger function processed a request.')
MY_CONNECTION_STRING = "STORAGE_ACCOUNT_STRING"
CONTAINER = "CONTAINERNAME"
LOCAL_PATH = "REPLACE_THIS"
 
class AzureBlobFileDownloader:
  def __init__(self):
    self.blob_service_client =  BlobServiceClient.from_connection_string(MY_CONNECTION_STRING)
    self.my_container = self.blob_service_client.get_container_client(CONTAINER)

  def save_blob(self,file_name,file_content):
    # Get full path to the file
    download_file_path = os.path.join(LOCAL_PATH, file_name)
    # for nested blobs, create local path as well!
    os.makedirs(os.path.dirname(download_file_path), exist_ok=True)
    with open(download_file_path, "wb") as file:
      file.write(file_content)

  def download_blobs_in_container(self):
    my_blobs = self.my_container.list_blobs()
    for blob in my_blobs:
      print(blob.name)
      bytes = self.my_container.get_blob_client(blob).download_blob().readall()
      self.save_blob(blob.name, bytes)

# Call the class.
azure_blob_file_downloader = AzureBlobFileDownloader()
azure_blob_file_downloader.download_all_blobs_in_container()

下面来自 Azure Python SDK 的代码将帮助您了解处理页面 blob 的高级方法

#Page Blob Operations
def page_blob_operations(self, account):
    file_to_upload = "HelloWorld.png"
    page_size = 1024;
    
    # Create an page blob service object
    pageblob_service = account.create_page_blob_service()
    container_name = 'pageblobcontainer' + self.random_data.get_random_name(6)

    try:
        # Create a new container
        print('1. Create a container with name - ' + container_name)
        pageblob_service.create_container(container_name)
        
        # Create a new page blob to upload the file
        print('2. Create a page blob')
        pageblob_service.create_blob(container_name, file_to_upload, page_size * 1024)
        
        # Read the file
        print('3. Upload pages to page blob')
        index = 0
        with open(file_to_upload, "rb") as file:
            file_bytes = file.read(page_size)
            while len(file_bytes) > 0:
                if len(file_bytes) < page_size:
                    file_bytes = bytes(file_bytes + bytearray(page_size - len(file_bytes)))
                    
                pageblob_service.update_page(container_name, file_to_upload, file_bytes, index * page_size, index * page_size + page_size - 1)
                
                file_bytes = file.read(page_size)
                
                index = index + 1
        
        pages = pageblob_service.get_page_ranges(container_name, file_to_upload)
        
        print('4. Enumerate pages in page blob')
        for page in pages:
            print('Page ' + str(page.start) + ' - ' + str(page.end))
    finally:
        print('5. Delete container')
        if pageblob_service.exists(container_name):
            pageblob_service.delete_container(container_name)

查看高级示例,其中显示了如何处理来自 Azure SDK for Python 的 Page、Block 和 Append blob。

参考 Azure Docs 处理 NodeJS 中的 blob。

答案既是又不是。

所有类型 blob 的下载都是相同的,即下载任何 blob 最终您将执行 Get Blob REST API 操作。当您执行此操作时,您可以下载任何类型的 blob。

然而,对于页面 blob,您可以通过仅下载占用的页面范围来优化下载。这叫做Sparse Download。本质上,您首先要做的是 find the occupied page ranges 在您的页面 blob 中,然后仅下载占用的页面范围。这样您就可以更快地下载页面 blob。例如,如果您有一个 128GB 的​​页面 blob,但它只包含 32GB 的数据(其余为空),那么通过使用稀疏下载方法,您将只下载 32GB 的数据。这对于其他 blob 类型是不可能的。

我没有检查最新版本的存储 SDK,但我很确定这些 SDK 在页面 blob 下载方面已经实现了稀疏下载。