使用PowerShell REST API查询Azure表存储未获取续传令牌怎么办?
解决Azure表存储REST API查询无法获取续传令牌的问题
你的代码未捕获响应头或正确读取响应体中的续传信息,导致无法获取下一批条目的令牌。Azure表存储返回超过1000条实体时,会通过两种方式提供续传数据:
- 响应头包含
x-ms-continuation-NextPartitionKey和x-ms-continuation-NextRowKey字段 - JSON响应体的
@odata.nextLink字段提供下一页完整请求URL
而当前使用Invoke-RestMethod默认仅返回响应体,不会保留响应头,也未检查响应体中的续传链接。
修正方案1:捕获响应头提取续传令牌
添加-ResponseHeadersVariable参数捕获响应头,从中提取续传键或直接读取响应体的@odata.nextLink:
$RGName = "MyResourceGroup" $StorageAccount = "MyStorageAccount" $TableName = "MyTable" $SA = Get-AzStorageAccount -Name $StorageAccount -ResourceGroupName $RGName -verbose $Accesskey = ($SA | Get-AzStorageAccountKey).value[0] $Version = "2021-08-06" $Table_url = "https://$StorageAccount.table.core.windows.net/$TableName" $GMTTime = (Get-Date).ToUniversalTime().toString('R') $stringToSign = "$GMTTime`n/$StorageAccount/$TableName" $HMACSHA = New-Object System.Security.Cryptography.HMACSHA256 $HMACSHA.key = [Convert]::FromBase64String($Accesskey) $Signature = $HMACSHA.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign)) $Signature = [Convert]::ToBase64String($Signature) $Headers = @{ 'x-ms-date' = $GMTTime Authorization = "SharedKeyLite " + $StorageAccount + ":" + $Signature "x-ms-version" = $Version Accept = "application/json;odata=fullmetadata" } # 调用API时捕获响应头到$respHeaders变量 $Item = Invoke-RestMethod -Method GET -Uri $Table_url -Headers $Headers -ContentType application/json -ResponseHeadersVariable respHeaders # 从响应头提取续传令牌并构建下一页URL if ($respHeaders['x-ms-continuation-NextPartitionKey']) { $nextPartitionKey = $respHeaders['x-ms-continuation-NextPartitionKey'] $nextRowKey = $respHeaders['x-ms-continuation-NextRowKey'] $nextUrl = "$Table_url?NextPartitionKey=$nextPartitionKey&NextRowKey=$nextRowKey" Write-Host "下一页请求URL:$nextUrl" } # 或直接读取响应体中的@odata.nextLink if ($Item.'@odata.nextLink') { Write-Host "下一页请求URL:$($Item.'@odata.nextLink')" }
修正方案2:自动循环获取所有条目
通过循环迭代,自动使用续传链接获取所有条目:
$RGName = "MyResourceGroup" $StorageAccount = "MyStorageAccount" $TableName = "MyTable" $SA = Get-AzStorageAccount -Name $StorageAccount -ResourceGroupName $RGName -verbose $Accesskey = ($SA | Get-AzStorageAccountKey).value[0] $Version = "2021-08-06" $currentUrl = "https://$StorageAccount.table.core.windows.net/$TableName" $allItems = @() while ($currentUrl) { $GMTTime = (Get-Date).ToUniversalTime().toString('R') # 签名使用固定路径/$StorageAccount/$TableName,不受URL查询参数影响 $stringToSign = "$GMTTime`n/$StorageAccount/$TableName" $HMACSHA = New-Object System.Security.Cryptography.HMACSHA256 $HMACSHA.key = [Convert]::FromBase64String($Accesskey) $Signature = $HMACSHA.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign)) $Signature = [Convert]::ToBase64String($Signature) $Headers = @{ 'x-ms-date' = $GMTTime Authorization = "SharedKeyLite " + $StorageAccount + ":" + $Signature "x-ms-version" = $Version Accept = "application/json;odata=fullmetadata" } $response = Invoke-RestMethod -Method GET -Uri $currentUrl -Headers $Headers -ContentType application/json -ResponseHeadersVariable respHeaders $allItems += $response.value # 优先使用响应体中的@odata.nextLink作为下一页URL $currentUrl = $response.'@odata.nextLink' # 若不存在则从响应头构建下一页URL if (-not $currentUrl -and $respHeaders['x-ms-continuation-NextPartitionKey']) { $nextPartitionKey = $respHeaders['x-ms-continuation-NextPartitionKey'] $nextRowKey = $respHeaders['x-ms-continuation-NextRowKey'] $currentUrl = "$Table_url?NextPartitionKey=$nextPartitionKey&NextRowKey=$nextRowKey" } } Write-Host "总共获取到$($allItems.Count)条条目"
关键注意点
- 每次发起下一页请求时,必须重新生成签名(
x-ms-date为当前UTC时间,签名需随时间更新) - 续传信息的存在形式取决于
Accept头设置,application/json;odata=fullmetadata会返回@odata.nextLink,同时响应头也会包含续传键
内容的提问来源于stack exchange,提问作者Lars Panzerbjrn
相关产品推荐
相关产品推荐

