Compartir a través de

使用 PowerShell 管理块 blob

Blob 存储支持块 blob、追加 blob 和页 blob。 块 blob 经过优化,可高效地上传大量数据。 块 Blob 非常适合存储图像、文档和其他不受随机读写操作影响的数据类型。 本文说明如何处理块 blob。

先决条件

配置上下文对象以封装凭据

对 Azure 存储的每个请求必须获得授权。 可以使用 Microsoft Entra 帐户或使用帐户访问密钥来授权从 PowerShell 发出的请求。 本文中的示例将 Microsoft Entra 授权与上下文对象配合使用。 上下文对象封装你的 Microsoft Entra 凭据并在后续数据操作期间传递它们。

若要使用 Microsoft Entra 帐户登录到你的 Azure 帐户,请打开 PowerShell 并调用 Connect-AzAccount cmdlet。

#Connect to your Azure subscription
Connect-AzAccount -Environment AzureChinaCloud

建立连接后,创建 Azure 上下文。 使用 Microsoft Entra ID 进行身份验证会自动为你的默认订阅创建 Azure 上下文。 在某些情况下,可能需要在进行身份验证后访问不同订阅中的资源。 可以通过修改活动会话上下文来更改与当前 Azure 会话关联的订阅。

若要使用默认订阅,请通过调用 New-AzStorageContext cmdlet 来创建上下文。 包含 -UseConnectedAccount 参数,以便使用 Microsoft Entra 凭据执行数据操作。

#Create a context object using Azure AD credentials
$ctx = New-AzStorageContext -StorageAccountName <storage account name> -UseConnectedAccount

若要更改订阅,请使用 Get-AzSubscription cmdlet 检索上下文对象,然后使用 Set-AzContext 更改当前上下文。 有关详细信息,请参阅更改活动订阅

创建容器

所有 Blob 数据都存储在容器中,因此你至少需要一个容器资源才能上传数据。 如果需要,请使用下面的示例创建存储容器。 有关详细信息,请参阅使用 PowerShell 管理 blob 容器

#Create a container object
$container = New-AzStorageContainer -Name "mycontainer" -Context $ctx

使用以下示例时,需要将括号中的占位符值替换为自己的值。 若要详细了解如何使用 PowerShell 登录 Azure,请参阅使用 Azure PowerShell 登录

上传 blob

若要将文件上传到块 blob,请将所需参数值传递给 Set-AzStorageBlobContent cmdlet。 使用 -File 参数提供路径和文件名,并使用 -Container 参数提供容器的名称。 还需要使用 -Context 参数提供对上下文对象的引用。

此命令会在 blob 不存在时创建它,或是在它存在提示进行覆盖确认。 如果将 -Force 参数传递给 cmdlet,则可以在无需确认的情况下覆盖文件。

下面的示例指定了一个 -File 参数值,用于上传单个命名文件。 它还演示如何使用 PowerShell 管道运算符和 Get-ChildItem cmdlet 上传多个文件。 Get-ChildItem cmdlet -Path 使用参数指定 C:\Temp\*.png。 包含星号 (*) 通配符 会指定具有 .png 文件扩展名的所有文件。 -Recurse 参数会搜索 Temp 目录及其子目录。

#Set variables
$path          = "C:\temp\" 
$containerName = "mycontainer"
$filename      = "demo-file.txt"
$imageFiles    = $path + "*.png"
$file          = $path + $filename

#Upload a single named file
Set-AzStorageBlobContent -File $file -Container $containerName -Context $ctx

#Upload multiple image files recursively
 Get-ChildItem -Path $imageFiles -Recurse | Set-AzStorageBlobContent -Container $containerName -Context $ctx

结果会显示存储帐户名称和存储容器名称,并提供上传的文件的列表。

   AccountName: demostorageaccount, ContainerName: demo-container

Name              BlobType   Length  ContentType                LastModified          AccessTier  IsDeleted
----              --------   ------  -----------                ------------          ----------  ---------
demo-file.txt     BlockBlob  222     application/octet-stream   2021-12-14 01:38:03Z  Cool        False     
hello-world.png   BlockBlob  14709   application/octet-stream   2021-12-14 01:38:03Z  Cool        False
hello-world2.png  BlockBlob  12472   application/octet-stream   2021-12-14 01:38:03Z  Cool        False
hello-world3.png  BlockBlob  13537   application/octet-stream   2021-12-14 01:38:03Z  Cool        False

列出 Blob

Get-AzStorageBlob cmdlet 用于列出容器中存储的 blob。 可以使用各种方法定义搜索范围。 使用 -Container-Name 参数可列出已知容器中的特定 blob。 若要为特定容器中的所有 blob 生成未筛选列表,请单独使用 -Container 参数,而不使用 -Name 值。

存储帐户可以具有的容器或 blob 数没有限制。 为了避免可能检索数千个 blob,最好限制返回的数据量。 检索多个 blob 时,可以使用 -Prefix 参数指定名称以特定字符串开头的 blob。 还可以将 -Name 参数与通配符一起使用来指定文件名或类型。

-MaxCount 参数可用于限制从容器返回的未筛选 blob 数。 对所有 Azure 资源上施加了 5,000 的服务限制。 此限制可确保检索到可管理的数据量并且不会影响性能。 如果返回的 blob 数超过 -MaxCount 值或服务限制,则返回延续令牌。 此令牌允许使用多个请求来检索任意数量的 Blob。 枚举 blob 资源上提供了详细信息。

下面的示例演示了几种用于提供 blob 列表的方法。 第一种方法列出特定容器资源中的单个 blob。 第二种方法使用通配符列出所有前缀为 Louis 的 .jpg 文件。 搜索使用 -MaxCount 参数限制为五个容器。 第三种方法使用 -MaxCount-ContinuationToken 参数限制为检索容器中的所有 blob。

#Set variables
$namedContainer  = "named-container"
$demoContainer   = "mycontainer"
$containerPrefix = "demo"

$maxCount = 1000
$total     = 0
$token     = $Null

#Approach 1: List all blobs in a named container
Get-AzStorageBlob -Container $namedContainer -Context $ctx

#Approach 2: Use a wildcard to list blobs in all containers
Get-AzStorageContainer -MaxCount 5 -Context $ctx | Get-AzStorageBlob -Blob "*louis*.jpg" 

#Approach 3: List batches of blobs using MaxCount and ContinuationToken parameters
Do
{
     #Retrieve blobs using the MaxCount parameter
     $blobs = Get-AzStorageBlob -Container $demoContainer `
         -MaxCount $maxCount `
         -ContinuationToken $token `
         -Context $ctx
     $blobCount = 1
     
     #Loop through the batch
     Foreach ($blob in $blobs)
     {
         #To-do: Perform some work on individual blobs here

         #Display progress bar
         $percent = $($blobCount/$maxCount*100)
         Write-Progress -Activity "Processing blobs" -Status "$percent% Complete" -PercentComplete $percent
         $blobCount++
     }

     #Update $total
     $total += $blobs.Count
      
     #Exit if all blobs processed
     If($blobs.Length -le 0) { Break; }
      
     #Set continuation token to retrieve the next batch
     $token = $blobs[$blobs.Count -1].ContinuationToken
 }
 While ($null -ne $token)
 Write-Host "`n`n   AccountName: $($ctx.StorageAccountName), ContainerName: $demoContainer `n"
 Write-Host "Processed $total blobs in $namedContainer."

前两种方法显示存储帐户和容器名称,以及检索到的 blob 列表。 第三种方法显示命名容器中的 blob 总数。 blob 分批进行检索,一个状态栏会显示计数期间的进度。

   AccountName: demostorageaccount, ContainerName: named-container

Name                 BlobType    Length    ContentType    LastModified          AccessTier    IsDeleted
----                 --------    ------    -----------    ------------          ----------    ---------
index.txt            BlockBlob   222       text/plain     2021-12-15 22:00:10Z  Cool          False
miles-davis.txt      BlockBlob   23454     text/plain     2021-12-15 22:17:59Z  Cool          False
cab-calloway.txt     BlockBlob   18419     text/plain     2021-12-15 22:17:59Z  Cool          False
benny-goodman.txt    BlockBlob   17726     text/plain     2021-12-15 22:17:59Z  Cool          False


   AccountName: demostorageaccount, ContainerName: demo-container

Name                 BlobType    Length    ContentType    LastModified          AccessTier    IsDeleted
----                 --------    ------    -----------    ------------          ----------    ---------
louis-armstrong.jpg  BlockBlob   211482    image/jpeg     2021-12-14 01:38:03Z  Cool          False
louis-jordan.jpg     BlockBlob   55766     image/jpeg     2021-12-14 01:38:03Z  Cool          False
louis-prima.jpg      BlockBlob   290651    image/jpeg     2021-12-14 01:38:03Z  Cool          False


   AccountName: demostorageaccount, ContainerName: demo-container

Processed 5257 blobs in demo-container.

下载 Blob

根据用例,Get-AzStorageBlobContent cmdlet 可以用于下载单个或多个 blob。 与大多数操作一样,这两种方法都需要上下文对象。

若要下载单个命名 blob,可以直接调用该 cmdlet 并提供 -Blob-Container 参数的值。 默认情况下,该 Blob 将下载到工作 PowerShell 目录,但也可以指定备用位置。 若要更改目标位置,必须使用 -Destination 参数传递有效的现有路径。 由于该操作无法创建目标,因此如果指定的路径不存在,则该操作会失败并出现错误。

可以通过将 Get-AzStorageBlob cmdlet 和 PowerShell 管道运算符结合使用来下载多个 blob。 首先,使用 Get-AzStorageBlob cmdlet 创建 blob 列表。 接下来,使用管道运算符和 Get-AzStorageBlobContent cmdlet 从容器检索 blob。

下面的示例代码提供了单一下载和多个下载方法的示例。 它还提供了一种简化方法来使用通配符搜索特定文件的所有容器。 由于某些环境可能具有数百个资源,因此建议使用 -MaxCount 参数。

#Set variables
$containerName = "mycontainer"
$path          = "C:\temp\downloads\"
$blobName      = "demo-file.txt"
$fileList      = "*.png"
$pipelineList  = "louis*"
$maxCount      = 10

#Download a single named blob
Get-AzStorageBlobContent -Container $containerName -Blob $blobName -Destination $path -Context $ctx

#Download multiple blobs using the pipeline
Get-AzStorageBlob -Container $containerName -Blob $fileList -Context $ctx | Get-AzStorageBlobContent

#Use wildcard to download blobs from all containers
Get-AzStorageContainer -MaxCount $maxCount `
     -Context $ctx | Get-AzStorageBlob `
     -Blob "louis*" | Get-AzStorageBlobContent

结果会显示存储帐户和容器名称,并提供下载的文件的列表。

   AccountName: demostorageaccount, ContainerName: demo-container

Name                 BlobType   Length  ContentType              LastModified          AccessTier  IsDeleted
----                 --------   ------  -----------              ------------          ----------  ---------
demo-file.txt        BlockBlob  222     application/octet-stream 2021-12-14 01:38:03Z  Unknown     False
hello-world.png      BlockBlob  14709   application/octet-stream 2021-12-14 01:38:03Z  Unknown     False
hello-world2.png     BlockBlob  12472   application/octet-stream 2021-12-14 01:38:03Z  Unknown     False
hello-world3.png     BlockBlob  13537   application/octet-stream 2021-12-14 01:38:03Z  Unknown     False

   AccountName: demostorageaccount, ContainerName: public-container

Name                 BlobType   Length  ContentType              LastModified          AccessTier  IsDeleted
----                 --------   ------  -----------              ------------          ----------  ---------
louis-armstrong.jpg  BlockBlob  211482  image/jpeg               2021-12-14 18:56:03Z  Unknown     False

   AccountName: demostorageaccount, ContainerName: read-only-container

Name                 BlobType   Length  ContentType              LastModified          AccessTier  IsDeleted
----                 --------   ------  -----------              ------------          ----------  ---------
louis-jordan.jpg     BlockBlob  55766   image/jpeg               2021-12-14 18:56:21Z  Unknown     False

   AccountName: demostorageaccount, ContainerName: hidden-container

Name                 BlobType   Length  ContentType              LastModified          AccessTier  IsDeleted
----                 --------   ------  -----------              ------------          ----------  ---------
louis-prima.jpg      BlockBlob  290651  image/jpeg               2021-12-14 18:56:45Z  Unknown     False

管理 blob 属性和元数据

容器会公开系统属性和用户定义的元数据。 每个 Blob 存储资源都存在系统属性。 有些属性是只读的,而其他属性可以读取或设置。 事实上,有些系统属性与某些标准 HTTP 头对应。

用户定义的元数据包含一个或多个你为 Blob 存储资源指定的名称/值对。 可以使用元数据存储资源的这些值。 元数据值仅用于你自己的目的,不会影响资源的行为方式。

读取 blob 属性

若要读取 blob 属性或元数据,必须首先从服务检索 blob。 使用 Get-AzStorageBlob cmdlet 可检索 blob 的属性和元数据,但不检索其内容。 接下来,使用 BlobClient.GetProperties 方法提取 blob 的属性。 随后可以根据需要读取或设置属性或元数据。

下面的示例检索 blob 并列出其属性。

$blob = Get-AzStorageBlob -Blob "blue-moon.mp3" -Container "mycontainer" -Context $ctx
$properties = $blob.BlobClient.GetProperties()
Echo $properties.Value

结果会显示 Blob 的属性列表,如以下示例所示。

LastModified                         : 11/16/2021 3:42:07 PM +00:00
CreatedOn                            : 11/16/2021 3:42:07 PM +00:00
Metadata                             : {}
BlobType                             : Block
LeaseDuration                        : Infinite
LeaseState                           : Available
LeaseStatus                          : Unlocked
ContentLength                        : 2163298
ContentType                          : audio/mpeg
ETag                                 : 0x8D9C0AA9E0CBA78
IsServerEncrypted                    : True
AccessTier                           : Cool
IsLatestVersion                      : False
TagCount                             : 0
ExpiresOn                            : 1/1/0001 12:00:00 AM +00:00
LastAccessed                         : 1/1/0001 12:00:00 AM +00:00
HasLegalHold                         : False

读取和写入 blob 元数据

Blob 元数据是与 blob 关联的名称/值对的可选集。 如上面的示例所示,最初没有与 blob 关联的元数据,但可以在需要时添加。 若要更新 Blob 元数据,请使用 BlobClient.UpdateMetadata 方法。 此方法只接受存储在泛型 IDictionary 对象中的键值对。 有关详细信息,请参阅 BlobClient 类定义。

下面的示例首先更新,随后提交 blob 的元数据,然后进行检索。 示例 blob 会从内存中刷新,以确保不会从内存中对象读取元数据。

#Set variable
$container = "mycontainer"
$blobName  = "blue-moon.mp3"

#Retrieve blob
$blob = Get-AzStorageBlob -Blob $blobName -Container $container -Context $ctx

#Create IDictionary, add key-value metadata pairs to IDictionary
$metadata = New-Object System.Collections.Generic.Dictionary"[String,String]"
$metadata.Add("YearWritten","1934")
$metadata.Add("YearRecorded","1958")
$metadata.Add("Composer","Richard Rogers")
$metadata.Add("Lyricist","Lorenz Hart")
$metadata.Add("Artist","Tony Bennett")

#Update metadata
$blob.BlobClient.SetMetadata($metadata, $null)

#Flush blob from memory, retrieve updated blob, retrieve properties
$blob = $null
$blob = Get-AzStorageBlob -Blob $blobName -Container $container -Context $ctx
$properties = $blob.BlobClient.GetProperties()
 
#Display metadata
Echo $properties.Value.Metadata

结果返回 Blob 的刚更新过的元数据,如以下示例所示。

Key          Value         
---          -----         
YearWritten  1934          
YearRecorded 1958          
Composer     Richard Rogers
Lyricist     Lorenz Hart   
Artist       Tony Bennett

用于 blob 的复制操作

在许多情况下,可能会复制不同类型的 blob。 本文中的示例仅限于块 blob。

将源 blob 复制到目标 blob

对于同一存储帐户中的简化复制操作,请使用 Copy-AzStorageBlob cmdlet。 由于该操作在同一存储帐户中复制 blob,因此这是同步操作。 跨帐户操作是异步的。

你应考虑使用 AzCopy 进行简化和提高性能,尤其是在存储帐户之间复制 blob 时。 AzCopy 是一个命令行实用工具,可用于向/从存储帐户复制 Blob 或文件。 了解有关如何开始使用 AzCopy 的详细信息。

下面的示例将 bannerphoto.png blob 从 photos 容器复制到 archive 容器中的 photos 文件夹 。 这两个容器处于同一个存储帐户中。 结果会验证复制操作是否成功。

$blobname = "bannerphoto.png"
Copy-AzStorageBlob -SrcContainer "photos" `
     -SrcBlob $blobname -DestContainer "archive" `
     -DestBlob $("photos/$blobname") -Context $ctx

AccountName: demostorageaccount, ContainerName: archive

Name                BlobType   Length  ContentType  LastModified          AccessTier  IsDeleted  VersionId
----                --------   ------  -----------  ------------          ----------  ---------  ---------
photos/bannerphoto  BlockBlob  12472   image/png    2021-11-27 23:11:43Z  Cool        False

可以使用 -Force 参数覆盖目标处具有相同名称的现有 blob。 此操作可有效地替换目标 blob。 它还会删除所有未提交的块,并覆盖目标 blob 的元数据。

将快照复制到具有不同名称的目标 Blob

生成的目标 Blob 是可写的 Blob,而不是快照。

复制操作的源 Blob 可以是块 Blob、追加 Blob、页 Blob 或快照。 如果目标 Blob 已存在,该 Blob 的类型必须与源 Blob 的类型相同。 将会覆盖现有的目标 Blob。

当复制操作正在进行时,无法修改目标 Blob。 目标 Blob 只能有一个未完成的复制操作。 换言之,一个 Blob 不能是多个挂起的复制操作的目标。

复制同一存储帐户中的 Blob 属于同步操作。 跨帐户复制操作是异步的。

始终复制整个源 Blob 或文件。 不支持复制字节范围或块集。

复制 Blob 时,会将系统属性复制到具有相同值的目标 Blob。

此外介绍如何中止异步复制操作。

快照 blob

快照是在某一时间点拍摄的只读版本的 Blob。 Blob 快照与其基本 Blob 相同,只是将 DateTime 值追加到 URI。 此值指示生成快照的时间,并提供基本 Blob 和快照之间的唯一区别。

任何与基本 Blob 关联的租约都不会影响快照。 无法获取快照上的租约。 详细了解 Blob 快照

下面的示例代码从存储容器检索 blob 并创建其快照。

$blob = Get-AzStorageBlob -Container "manuscripts" -Blob "novels/fast-cars.docx" -Context $ctx
$blob.BlobClient.CreateSnapshot()

设置 blob 层

更改 blob 的层时,会将 blob 及其所有数据移动到目标层。 若要进行更改,请使用 Get-AzStorageBlob cmdlet 检索 Blob,然后调用 BlobClient.SetAccessTier 方法。 此方法可用于在“热”、“冷”与“存档”之间更改层级。

几乎会立即将层级从“冷”或“热”更改为“存档”。 在 Blob 移动到“存档”层之后,它被视为处于脱机状态,无法读取或修改。 在读取或修改存档 Blob 的数据之前,必须首先将其解除冻结并置于联机层。 详细了解存档层中的 Blob 解除冻结

下面的示例代码对于 archive 容器中的所有 Blob 将层级设置为“热”。

$blobs = Get-AzStorageBlob -Container archive -Context $ctx
Foreach($blob in $blobs) {
    $blob.BlobClient.SetAccessTier("Hot")
}

使用 Blob 标记的操作

Blob 索引标记可简化数据管理和发现。 Blob 索引标记是用户定义的键值索引属性,可以应用于 Blob。 配置这些标记后,可以在单个容器或所有容器中对对象进行分类和查找。 Blob 资源可以通过更新其索引标记来动态分类,而无需更改容器组织。 索引标记提供一种灵活的方式来应对不断变化的数据需求。 可以同时使用元数据和索引标记。 有关索引标记详细信息,请查看通过 blob 索引标记管理和查找 Azure Blob 数据

以下示例说明了如何将 Blob 索引标记添加到一系列 Blob。 该示例从 XML 文件中读取数据并使用它在多个 Blob 上创建索引标签。 要使用示例代码,请在 C:\temp 目录中创建一个本地 blob-list.xml 文件。 以下示例提供了 XML 数据。

<Venue Name="House of Prime Rib" Type="Restaurant">
  <Files>
    <File path="transactions/12027121.csv" />
    <File path="campaigns/radio-campaign.docx" />
    <File path="photos/bannerphoto.png" />
    <File path="archive/completed/2020review.pdf" />
    <File path="logs/2020/01/01/logfile.txt" />
  </Files>
</Venue>

示例代码将创建一个哈希表,并将 $tags 变量分配给该表。 接下来,示例代码使用 Get-ContentGet-Data cmdlet 基于 XML 结构创建一个对象。 然后,它将键值对添加到要用作标记值的哈希表。 最后,它遍历 XML 对象并为每个 File 节点创建标记。

#Set variables
$filePath = "C:\temp\blob-list.xml"
$tags     = @{}

#Get data, set tag key-values
[xml]$data = Get-Content -Path $filepath
$tags.Add("VenueName", $data.Venue.Name)
$tags.Add("VenueType", $data.Venue.Type)
 
#Loop through files and add tag
$data.Venue.Files.ChildNodes | ForEach-Object {
    #break the path: container name, blob
    $path = $_.Path -split "/",2
   
    #set apply the blob tags
    Set-AzStorageBlobTag -Container $location[0] -Blob $location[1] -Tag $tags -Context $ctx
 }

删除 Blob

可以使用 Remove-AzStorageBlob cmdlet 删除单个 blob 或一系列 blob。 删除多个 Blob 时,可以利用条件操作、循环或 PowerShell 管道,如以下示例所示。

警告

运行以下示例可能会永久删除 Blob。 Azure 建议启用容器软删除,防止意外删除容器和 Blob。 有关详细信息,请参阅容器的软删除

#Create variables
$containerName  = "mycontainer"
$blobName       = "demo-file.txt"
$prefixName     = "file"

#Delete a single, named blob
Remove-AzStorageBlob -Blob $blobName -Container $containerName -Context $ctx

#Iterate a loop, deleting blobs
for ($i = 1; $i -le 3; $i++) { 
    Remove-AzStorageBlob -Blob (-join($prefixName, $i, ".txt")) -Container $containerName -Context $ctx
} 

#Retrieve blob list, delete using a pipeline
Get-AzStorageBlob -Prefix $prefixName -Container $containerName -Context $ctx | Remove-AzStorageBlob

在某些情况下,可以检索已删除的 blob。 如果已启用存储帐户的软删除数据保护选项,则 -IncludeDeleted 参数将返回在关联保留期内删除的 Blob。 若要了解有关软删除的详细信息,请参阅 blob 的软删除一文。

使用下面的示例可检索在容器关联保持期内删除的 blob 列表。 结果会显示最近删除的 blob 列表。

#Retrieve a list of blobs including those recently deleted
Get-AzStorageBlob -Prefix $prefixName -IncludeDeleted -Context $ctx

AccountName: demostorageaccount, ContainerName: demo-container

Name       BlobType   Length  ContentType                LastModified          AccessTier    IsDeleted
----       --------   ------  -----------                ------------          ----------    ---------
file.txt   BlockBlob  22      application/octet-stream   2021-12-16 20:59:41Z  Cool          True
file2.txt  BlockBlob  22      application/octet-stream   2021-12-17 00:14:24Z  Cool          True
file3.txt  BlockBlob  22      application/octet-stream   2021-12-17 00:14:24Z  Cool          True
file4.txt  BlockBlob  22      application/octet-stream   2021-12-17 00:14:25Z  Cool          True

还原已删除的 Blob

列出 blob 部分中所述,可以对存储帐户配置软删除数据保护选项。 启用后,可以还原在关联保留期内删除的 Blob。 你还可以使用版本控制来为每一次恢复和还原保留 Blob 的早期版本。

如果 Blob 版本控制和 Blob 软删除均已启用,那么,修改、改写、删除或还原 Blob 会自动创建新版本。 用于还原已删除 Blob 的方法将取决于存储帐户上是否启用了版本控制。

以下代码示例还原所有已软删除的 Blob,如果启用了版本控制,则还原 Blob 的最新版本。 它先用 Get-AzStorageBlobServiceProperty cmdlet 来确定是否启用了版本控制。

如果启用了版本控制,Get-AzStorageBlob cmdlet 会检索所有以唯一方式命名的 Blob 版本的列表。 接下来,检索列表中的 Blob 版本并按日期将它们排序。 如果未找到具有 LatestVersion 属性值的版本,则使用 Copy-AzBlob cmdlet 来制作最新版本的活动副本。

如果禁用了版本控制,则使用 BlobBaseClient.Undelete 方法来还原容器中每个被软删除的 Blob。

在按照此示例操作之前,需要先在至少一个存储帐户上启用软删除或版本控制。

重要

以下示例枚举一组 Blob,并在处理它们之前将其存储在内存中。 如果启用了版本控制,则也会对 Blob 进行排序。 将 -ContinuationToken 参数与 $maxCount 变量一起使用会限制组中 Blob 的数量,从而可节省资源。 如果容器包含数百万个 Blob,则成本将非常高。 可以调整 $maxCount 变量的值,但如果容器包含数百万个 Blob,则脚本将缓慢处理这些 Blob。

若要了解有关软删除数据保护选项的详细信息,请参阅 blob 的软删除一文。

$accountName   ="myStorageAccount"
$groupName     ="myResourceGroup"
$containerName ="mycontainer"
$maxCount      = 1000
$token         = $null


$blobSvc = Get-AzStorageBlobServiceProperty `
    -StorageAccountName $accountName `
    -ResourceGroupName $groupName

# If soft delete is enabled
if($blobSvc.DeleteRetentionPolicy.Enabled)
{
    # If versioning is enabled
    if($blobSvc.IsVersioningEnabled -eq $true)
    {
        # Set context
        $ctx = New-AzStorageContext `
            -StorageAccountName $accountName `
            -UseConnectedAccount
        do
        {
            # Get all blobs and versions using -Unique 
            # to avoid processing duplicates/versions
            $blobs = Get-AzStorageBlob `
                -Container $containerName `
                -Context $ctx -IncludeVersion | `
                    Where-Object {$_.VersionId -ne $null} | `
                    Sort-Object -Property Name -Unique

            # Iterate the collection
            foreach ($blob in $blobs)
            {
                # Process versions
                if($blob.VersionId -ne $null)
                {
            
                    # Get all versions of the blob, newest to oldest
                    $delBlob = Get-AzStorageBlob `
                        -Container $containerName `
                        -Context $ctx `
                        -Prefix $blob.Name `
                        -IncludeDeleted -IncludeVersion  | `
                            Sort-Object -Property VersionId -Descending

                    # Verify that the newest version is NOT the latest (that the version is "deleted")
                    if (-Not $delBlob[0].IsLatestVersion)
                    {
                        $delBlob[0] | Copy-AzStorageBlob `
                            -DestContainer $containerName `
                            -DestBlob $delBlob[0].Name
                    }
                
                    #Dispose the temporary object
                    $delBlob = $null
                }
            }
            $token = $blobs[$blobs.Count -1].ContinuationToken;
        }
        while ($null -ne $token)
    }

    # Otherwise (if versioning is disabled)
    else
    {
        $blobs = Get-AzStorageBlob `
            -Container $containerName `
            -Context $ctx -IncludeDeleted | `
                Where-Object {$_.IsDeleted}
        foreach($blob in $blobs)
        {
            if($blob.IsDeleted) { $blob.BlobBaseClient.Undelete() }
        }
    }
}
else
{
    echo "Sorry, the delete retention policy is not enabled."
}

后续步骤