首页 > 解决方案 > 在 PowerShell 中调用 Microsoft Graph API 上传端点时内容长度无效

问题描述

更新:此问题与 pwsh 7.1 和 5.1 之间的差异有关。脚本适用于 5.1 但不适用于 7.1。可能是编码问题。我尝试将 Content-Type 设置为 'application/octet-stream; charset=utf-8' 但没关系

我有一个 pwsh 脚本,它为我们的 CI 管道做了一些事情:

  1. 创建会话上传端点
  2. 将文件拆分为 byteArray 块
  3. 将每个块上传到上传端点

该脚本在我们所有的 AppVeyor 管道中运行良好,但现在我尝试在本地运行它(在将其添加到 Jenkins 之前进行测试),但我遇到了一个我没想到的错误。

上传块的函数:

function UploadFile([string] $accessToken, [string] $sourceFilePath, [string] $uploadUrl, [int] $chunkSize)
{
    $header = @{"Authorization" = "bearer $accessToken"}
            
    $fileStream = [System.IO.File]::OpenRead($sourceFilePath)

    $numberOfChunks = GetNumberOfChunks -chunkSize $chunkSize -bytes $fileStream.Length

    for ($i = 1 ; $i -le $numberOfChunks ; $i++){
   
        $filePos = $fileStream.Position

        if ($i -eq $numberOfChunks){
            $lastChunkSize = $fileStream.Length - $filePos 
                
            [byte[]]$fileChunk = New-Object byte[] $lastChunkSize 

            $bytesRead = $fileStream.Read($fileChunk, 0, $lastChunkSize);
        }
        else {        
            [byte[]]$fileChunk = New-Object byte[] $chunkSize
            $bytesRead = $fileStream.Read($fileChunk, 0, $chunkSize);
        }   

        $header["Content-Length"] = $bytesRead

        $header["Content-Range"] = "bytes $filePos-$($filePos + $bytesRead - 1)/$($fileStream.Length)"
            
        Write-Host "Uploading chunk $i of $numberOfChunks to OneDrive..."
        $uploadResult = Invoke-RestMethod -Headers $header -Method Put -Uri $uploadUrl -Body $fileChunk -SkipHeaderValidation   
    }

    $fileStream.Close
    $fileStream.Dispose

    RETURN $uploadResult
}

下面是一些调试输出,显示了 vars 和错误的值:

输出和错误信息

同样的方法在我们的 AppVeyor 项目中运行良好。我不知道为什么它在本地对我不起作用(Win 10 x64 和 PowerShell 7.1)。我尝试将 $bytesRead (int) 转换为字符串,但没有任何区别。想知道这可能不是数学问题,而是 Content-Length 标头选项的类型问题。任何想法表示赞赏。谢谢。

标签: powershellrestmicrosoft-graph-api

解决方案


嗯,原来 powershell 7 不喜欢我手动设置 Content-Length。从标题中删除它,并让 Invoke-RestMethod 自动设置 Content-Length,解决了这个问题。和以前一样,我设置的只是 Content-Range,现在我可以从我们的 linux Jenkins 盒子将块上传到 OneDrive。


推荐阅读