Windows虚拟机中PowerShell脚本无法上传Zip文件至存储账户
Azure存储Blob上传403权限问题排查与解决
问题详情
在Windows Server 2019 Datacenter虚拟机中执行PowerShell脚本上传文件C:\Data\Archive\20240312_Log.zip至Azure存储账户的logs容器时,收到403权限错误:
Message: Response status code does not indicate success: 403 (This request is not authorized to perform this operation.). CategoryInfo InvalidOperation: (Method: PUT, Reques…-Length: 6159687 }:HttpRequestMessage) [Invoke-RestMethod], HttpResponseException FullyQualifiedErrorId: WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand StackTrace: at SendToStorageAccount, <No file>: line 18 at <ScriptBlock>, <No file>: line 1 The File 20240312_Log.zip FAILED to upload
已知条件:
- 已为
logs容器创建SAS令牌 - 存储账户网络限制设置为「允许所有网络访问」
- 使用带笔记本IP白名单的SAS令牌,在本地笔记本执行相同脚本可成功上传
使用的上传脚本:
function SendToStorageAccount { param ( [string] $zipFileName ) $myDevSas = [System.Environment]::GetEnvironmentVariable('myDevSas','Machine') #The target URL wit SAS Token $uri = "https://mystdev.blob.core.windows.net/logs/$($zipFileName)?$($myDevSas)" #Define required Headers $headers = @{ 'x-ms-blob-type' = 'BlockBlob' } #Upload File... $apiCall try { $apiCall = Invoke-RestMethod -Uri $uri -Method Put -Headers $headers -InFile $zipFileName Write-Output $apiCall Write-Output "The File $($zipFileName) uploaded successfully" Remove-Item $zipFileName } catch { "Message: $($_.Exception.Message)" "CategoryInfo $($_.CategoryInfo)" "FullyQualifiedErrorId: $($_.FullyQualifiedErrorId)" "StackTrace: $(($_.ScriptStackTrace -replace '^'))" Write-Output $apiCall Write-Output "The File $($zipFileName) FAILED to upload" } } $fileName = "20240312_Log.zip" SendToStorageAccount $fileName
排查步骤
- 验证SAS令牌属性:确认SAS令牌包含**写入(Write)**权限,未过期,且未添加IP地址限制(即使存储账户允许所有网络,SAS本身的IP过滤会优先生效)
- 检查环境变量有效性:在虚拟机中执行
[System.Environment]::GetEnvironmentVariable('myDevSas','Machine'),输出值是否与正确的SAS令牌完全一致,无截断或多余字符 - 确认文件路径正确性:脚本中传入的
$fileName是相对路径,需验证虚拟机当前工作目录下是否存在该文件,或直接使用完整路径C:\Data\Archive\20240312_Log.zip - 检查SAS签名完整性:确保SAS令牌的
sig参数完整,复制过程中未丢失字符
解决建议
重新生成无限制的SAS令牌
登录Azure门户,进入存储账户的logs容器,生成新的容器级SAS令牌:- 权限勾选写入
- 不设置IP地址范围
- 有效期设置为合理时长
生成后更新虚拟机的myDevSas系统环境变量,重启PowerShell会话生效
修正脚本中的文件路径
将脚本中的$fileName改为完整路径:$fileName = "C:\Data\Archive\20240312_Log.zip"添加调试输出定位问题
在脚本中添加调试语句,确认关键参数:function SendToStorageAccount { param ( [string] $zipFileName ) $myDevSas = [System.Environment]::GetEnvironmentVariable('myDevSas','Machine') # 调试:输出SAS令牌(注意不要泄露到公共场合) Write-Output "SAS Token: $myDevSas" # 调试:验证文件是否存在 Write-Output "File exists: $(Test-Path $zipFileName)" $uri = "https://mystdev.blob.core.windows.net/logs/$($zipFileName | Split-Path -Leaf)?$($myDevSas)" # 调试:输出完整请求URI Write-Output "Request URI: $uri" $headers = @{ 'x-ms-blob-type' = 'BlockBlob' } try { $apiCall = Invoke-RestMethod -Uri $uri -Method Put -Headers $headers -InFile $zipFileName Write-Output $apiCall Write-Output "The File $($zipFileName) uploaded successfully" Remove-Item $zipFileName } catch { "Message: $($_.Exception.Message)" "CategoryInfo $($_.CategoryInfo)" "FullyQualifiedErrorId: $($_.FullyQualifiedErrorId)" "StackTrace: $(($_.ScriptStackTrace -replace '^'))" Write-Output $apiCall Write-Output "The File $($zipFileName) FAILED to upload" } }使用Azure PowerShell模块简化上传
替代Invoke-RestMethod,使用官方模块更稳定:# 安装Az.Storage模块(首次运行) Install-Module -Name Az.Storage -Force -AllowClobber -Scope CurrentUser $myDevSas = [System.Environment]::GetEnvironmentVariable('myDevSas','Machine') $storageContext = New-AzStorageContext -StorageAccountName "mystdev" -SasToken $myDevSas $filePath = "C:\Data\Archive\20240312_Log.zip" $blobName = (Get-Item $filePath).Name try { Set-AzStorageBlobContent -Context $storageContext -Container "logs" -File $filePath -Blob $blobName -Force Write-Output "文件 $blobName 上传成功" Remove-Item $filePath } catch { Write-Error "上传失败:$($_.Exception.Message)" }
内容的提问来源于stack exchange,提问作者scv
相关产品推荐
相关产品推荐

