Powershell 无法使用多部分表单数据将超过 ~50MB 的 zip 文件上传到 REST API

问题描述 投票:0回答:2

我在 .net core 3.1 中有一个 REST API 端点,如下所示:

        [Route("Install")]
        [HttpPost]
        [RequestSizeLimit(524288000)]
        public async Task<IActionResult> AddInstallFile(List<IFormFile> files)

我可以通过以下命令使用 cURL 上传文件:

curl -X POST MYURL Content-Type: multipart/form-data" -F "[email protected];type=application/x-zip-compressed"

它也可以通过 swagger 工作

在 powershell 中,虽然 Multipart/form-data 本身不支持,所以我使用以下代码上传到那里(本质上我使用了 chrome 开发工具中的“复制为 Powershell”功能的工作 swagger 上传来创建此代码):

$fileBytes = [System.IO.File]::ReadAllBytes("C:\Temp\filename.zip");
$enc = [System.Text.Encoding]::GetEncoding('utf-8')
$fileEnc = $enc.GetString($fileBytes)
    

Invoke-WebRequest -Uri "MYURL" `
-Method "POST" `
-Headers @{
 "method"="POST"
 "accept"="application/octet-stream"
 "accept-encoding"="gzip, deflate, br"
} `
-ContentType "multipart/form-data; boundary=----WebKitFormBoundaryT2XycANuthCIUwGk" `
-Body ([System.Text.Encoding]::UTF8.GetBytes("------WebKitFormBoundaryT2XycANuthCIUwGk$([char]13)$([char]10)Content-Disposition: form-data; name=`"files`"; filename=`"filename.zip`"$([char]13)$([char]10)Content-Type: application/x-zip-compressed$([char]13)$([char]10)$([char]13)$([char]10)$fileEnc$([char]13)$([char]10)------WebKitFormBoundaryT2XycANuthCIUwGk--$([char]13)$([char]10)"))

此 Powershell 代码对于我拥有的小于 2MB 的 zip 文件工作正常,但对于另一个超过 80MB 的 zip 文件则失败

服务器上的错误在这里:

An unhandled exception has occurred while executing the request.

Exception: 
System.ArgumentNullException: Value cannot be null. (Parameter 'source')
   at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
   at System.Linq.Enumerable.Sum[TSource](IEnumerable`1 source, Func`2 selector)
   at netproject.ControllerClass.AddInstallFile(List`1 files) in ControllerClass.cs:line 44

本质上,当从 powershell 调用超过 50MB 的文件时,files 变量将显示为 null。 我尝试了 Invoke-WebRequest 和 Invoke-RestMethod ,结果相同

powershell rest .net-core
2个回答
0
投票

对于将来遇到此问题的任何人 - 如果您在 powershell 中获得有效的解决方案,我仍然有兴趣了解它。为了暂时解决这个问题,我使用 .net 框架来上传文件。代码在这里:

    Write-Host "Uploading $name"
    $url = "URL_TO_UPLOAD"
    $file = "FULL_PATH_ZIP_FILE"

    $fs = [System.IO.FileStream]::New($file, [System.IO.FileMode]::Open)
    $f1 = New-Object System.Net.Http.StreamContent $fs

    $client = New-Object System.Net.Http.HttpClient 
    $client.DefaultRequestHeaders.ConnectionClose = $true 
    $client.DefaultRequestHeaders.Add("Authorization", $auth);

    $form = New-Object System.Net.Http.MultipartFormDataContent
    $form.Add($f1, 'files', $name)

    $rsp = $client.PostAsync($url, $form).Result
    Write-Host "Upload status: " + $rsp.StatusCode

    $fs.Close(); 
    $fs.Dispose()

0
投票

这种方法对我有用(假设您已经通过

-SessionVariable
存储的会话进行了身份验证):

$ImagePath = "C:\test.jpg"

# extract the image file name, without path
$fileName = Split-Path $imagePath -Leaf

# grab the raw bytes composing the image file
$imageBytes = [Io.File]::ReadAllBytes($imagePath)
$fileEnc = [System.Text.ASCIIEncoding]::GetEncoding('UTF-8').GetString($imageBytes);

#Set random boundary string for header
$boundary = [guid]::NewGuid().ToString()
$LF = "`r`n";

$bodyLines = ( 
    "--$boundary",
    "Content-Disposition: form-data; name=`"fileSize`"$LF",
    "$($imageBytes.Length)",
    "--$boundary",
    "Content-Disposition: form-data; name=`"file`"; filename=`"$($fileName)`"",
    "Content-Type: image/jpeg$LF",
    $fileEnc,
    "--$boundary--$LF"
) -join $LF

$UploadResponse = Invoke-RestMethod -Uri $URL -Method Post -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $bodyLines -WebSession $Session

话虽如此,curl 现在默认包含在 Windows 10+ 中,并且在我看来要容易得多,您只需确保使用

curl.exe
,因为
curl
是一个 invoke-webrequest 别名 -_-

© www.soinside.com 2019 - 2024. All rights reserved.