You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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参数完整,复制过程中未丢失字符

解决建议

  1. 重新生成无限制的SAS令牌
    登录Azure门户,进入存储账户的logs容器,生成新的容器级SAS令牌:

    • 权限勾选写入
    • 不设置IP地址范围
    • 有效期设置为合理时长
      生成后更新虚拟机的myDevSas系统环境变量,重启PowerShell会话生效
  2. 修正脚本中的文件路径
    将脚本中的$fileName改为完整路径:

    $fileName = "C:\Data\Archive\20240312_Log.zip"
    
  3. 添加调试输出定位问题
    在脚本中添加调试语句,确认关键参数:

    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"
        }
    }
    
  4. 使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 02:44:51