Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带PowerShell的HTTP POST多部分/表单数据二进制数据_Powershell - Fatal编程技术网

带PowerShell的HTTP POST多部分/表单数据二进制数据

带PowerShell的HTTP POST多部分/表单数据二进制数据,powershell,Powershell,在W2K12 R2 x64上使用PS 5.1.14409.1005 就我所知,有两种方法可以做到这一点- 按照RFC格式手动创建多部分/表单正文 使用MultipartFormDataContent.NET类型 我尝试了MultipartFormDataContent,但当我将构造的对象添加到Invoke WebRequest的body参数时,它不起作用(例如,请参见下面的示例),并且我成功地使用文本表单部分手动构造,但在使用二进制时遇到了问题。屏幕截图显示了一个来自powershell的Inv

在W2K12 R2 x64上使用PS 5.1.14409.1005

就我所知,有两种方法可以做到这一点-

  • 按照RFC格式手动创建多部分/表单正文
  • 使用MultipartFormDataContent.NET类型
  • 我尝试了MultipartFormDataContent,但当我将构造的对象添加到
    Invoke WebRequest
    的body参数时,它不起作用(例如,请参见下面的示例),并且我成功地使用文本表单部分手动构造,但在使用二进制时遇到了问题。屏幕截图显示了一个来自powershell的
    Invoke WebRequest
    的fiddler请求捕获,它不起作用,另一个来自chrome,它起作用。二进制内容是不同的,我不知道如何获得与chrome相同的内容

    以下是前几个十六进制字节,将实际文件与chrome和powershell在fiddler中发送的文件进行比较。其余的部分都有一些小的区别

    file:   30 82 1D 32 02 01 03 30 82 1C F8
    chrome: 30 82 1D 32 02 01 03 30 82 1C F8
    ps:     30 2C 1D 32 02 01 03 30 2C 1C F8
    
    这是我目前的代码。二进制部分由
    Get Content-Path$FilePath-Raw
    填充

    function Publish-RestApiFile {
        param ([string] $Url, [hashtable] $Params, [string] $FilePath, [string] $FileParamName)
        Add-Type -AssemblyName System.Web
        $bnd = [System.Guid]::NewGuid().ToString().ToLower().Replace('-','').PadLeft(40,'-')
        $content_type = "multipart/form-data; boundary=$bnd"
        $LF = "`r`n"
        $lines = @("--${bnd}${LF}")
        $Params.GetEnumerator() | ForEach-Object {
            $lines += "$('Content-Disposition: form-data; name="{0}"' -f $_.Name)${LF}${LF}$($_.Value)${LF}"
            $lines += "--${bnd}${LF}"
        }
        $file_name = Split-Path -Path $FilePath -Leaf
        $mime_type = [System.Web.MimeMapping]::GetMimeMapping($FilePath)
        $ct = Get-Content -Path $FilePath -Raw
        $lines += ('Content-Disposition: form-data; name="{0}"; filename="{1}"' -f $FileParamName,$file_name)+${LF}
        $lines += ("Content-Type: ${mime_type}${LF}${LF}"),$ct,${LF}
        $lines += ("--${bnd}--"+${LF})
        $lines = $lines -join ''
        Invoke-RestMethod -Uri $url -Method Post -Body $lines -ContentType $content_type -MaximumRedirection 0
    }
    
    显示当前代码生成的正文字符串-

    这显示了PS
    Invoke WebRequest
    (左)和chrome(右)在fiddler中捕获的请求的二进制差异。

    下面是使用MultipartFormDataContent的示例。Fiddler显示对象正被强制转换为正文中的字符串,例如
    System.Net.Http.StringContent System.Net.Http.StringContent System.Net.Http.StreamContent系统.Net.Http.StreamContent

    function Publish-RestApiFile2 {
        param ([string] $Url, [hashtable] $Params, [string] $FilePath, [string] $FileParamName)
        Add-Type -AssemblyName System.Net.Http, System.Web
    
        $mime_type = [System.Web.MimeMapping]::GetMimeMapping($FilePath)
        $form = [System.Net.Http.MultipartFormDataContent]::New()
        foreach ($param in $Params.GetEnumerator()) {
            $header = [System.Net.Http.Headers.ContentDispositionHeaderValue]::new("form-data")
            $header.Name = $param.Name
            $content = [System.Net.Http.StringContent]::new($param.Value)
            $content.Headers.ContentDisposition = $header
            $form.Add($content)
        }
        $stream = [System.IO.FileStream]::New($FilePath, 'Open')
        $header = [System.Net.Http.Headers.ContentDispositionHeaderValue]::new("form-data")
        $header.Name = $FileParamName
        $header.FileName = (Split-Path -Path $FilePath -Leaf)
        $content = [System.Net.Http.StreamContent]::New($stream)
        $content.Headers.ContentDisposition = $header
        $content.Headers.ContentType = [System.Net.Http.Headers.MediaTypeHeaderValue]::Parse($mime_type)
        $form.Add($content)
    
        Invoke-WebRequest -Uri $Url -Method Post -Body $form -ContentType 'multipart/form-data'
        #Invoke-WebRequest -Uri $Url -Method Post -Body $form
        $stream.Close(); $stream.Dispose()
    }
    

    我使用所有.NET类型而不是
    Invoke-WebRequest
    -

    如果它有助于某人-

    Add-Type -AssemblyName System.Net.Http
    
    $url = "https://server.local/restendpoint"
    $file = "C:\cert.pfx"
    
    $fs = [System.IO.FileStream]::New($file, [System.IO.FileMode]::Open)
    
    $s1 = New-Object System.Net.Http.StringContent 'alias_value'
    $s2 = New-Object System.Net.Http.StringContent 'password_value'
    $f1 = New-Object System.Net.Http.StreamContent $fs
    
    $handler = New-Object System.Net.Http.HttpClientHandler
    $handler.AllowAutoRedirect = $false # Don't follow after post redirect code 303
    $client = New-Object System.Net.Http.HttpClient -ArgumentList $handler
    $client.DefaultRequestHeaders.ConnectionClose = $true # Disable keep alive, get a 200 response rather than 303
    $form = New-Object System.Net.Http.MultipartFormDataContent
    
    $form.Add($s1, 'alias')
    $form.Add($s2, 'password')
    $form.Add($f1, 'file', 'cert.pfx')
    
    $rsp = $client.PostAsync($u, $form).Result
    $rsp.IsSuccessStatusCode # false if 303
    $rsp.StatusCode -eq 303 # true if 303
    
    $fs.Close(); $fs.Dispose()
    

    您是否尝试过用[Io.File]::ReadAllBytes()替换Get内容?我发现Get内容存在许多与性能相关的问题,我会不惜一切代价避免这些问题。