分享方式:


使用 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

連線建立後,請建立 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。 Microsoft 建議啟用容器虛刪除,以防止容器和 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."
}

下一步