【问题标题】:Create custom POST-request body in PowerShell在 PowerShell 中创建自定义 POST 请求正文
【发布时间】:2015-12-03 10:52:34
【问题描述】:

我遇到了一些麻烦。我正在尝试使用 PowerShell 进行 POST 请求。问题是请求正文多次使用相同的密钥(您可以上传多张图片),因此我无法构建哈希表来发送请求。所以 requestbody 看起来像这样:

name               value

image              1.jpg
image              2.jpg
subject            this is the subject
message            this is a message

一个有类似问题(但上下文不同)的用户之前问过这个问题,并得到了使用带有 KeyValuePair 类的 List 作为响应。见https://stackoverflow.com/a/5308691/4225082

我似乎无法创建这个。我找到了这个https://bensonxion.wordpress.com/2012/04/27/using-key-value-pairs-in-powershell-2/ 他们使用$testDictionary=New-Object “System.Collections.Generic.Dictionary[[System.String],[System.String]]” 制作字典,但这不会转化为列表。

我设法通过使用$r = New-Object "System.Collections.Generic.List[System.Collections.Generic.KeyvaluePair[string,string]]" 创建(我认为需要的) 并使用$s = New-Object “System.Collections.Generic.KeyvaluePair[string,string]" 创建了一个键,但我无法设置该键的值。

我也尝试过创建一个 FormObject,但你也不能多次使用同一个键。

最好和/或最简单的方法是什么?

【问题讨论】:

  • 谢谢你,我现在可以填写我的清单了!它似乎没有按预期工作。我在该列表中输入的所有内容在请求中都显示为一个长的单个字符串,而不是名称-值对:(

标签: list powershell post webrequest keyvaluepair


【解决方案1】:

我将回答我自己的问题。由于研究,我设法使用更好的搜索词,并找到了完全相同的问题: Does Invoke-WebRequest support arrays as POST form parameters?

通过将[HttpWebResponse] 更改为[System.Net.HttpWebResponse] 并添加了-WebSession 参数,我摆脱了一个错误(?)。我只需要它来处理 cookie,所以我实现了它并且没有打扰其他东西,它可能需要为其他人做一些调整!

乍一看这似乎有效,但是对于具有相同键的元素,它创建了一个数组,这弄乱了请求正文的顺序。没有正确的订单,网站不会接受。

我搞砸了一点,现在我编辑它以利用多维数组。 所以我最终得到了这个(所有功劳归于原作者!):

function Invoke-WebRequestEdit
{
    [CmdletBinding()]
    Param
    (
    [Parameter(Mandatory=$true)][System.Uri] $Uri,
    [Parameter(Mandatory=$false)][System.Object] $Body,
    [Parameter(Mandatory=$false)][Microsoft.PowerShell.Commands.WebRequestMethod] $Method,
    [Parameter(Mandatory=$false)][Microsoft.PowerShell.Commands.WebRequestSession] $WebSession
    # Extend as necessary to match the signature of Invoke-WebRequest to fit your needs.
    )
    Process
    {
        # If not posting a NameValueCollection, just call the native Invoke-WebRequest.
        if ($Body -eq $null -or $body.GetType().BaseType -ne [Array]) {
            Invoke-WebRequest @PsBoundParameters
            return;
        }

        $params = "";    
        $i = 0;
        $j = $body.Count;
        $first = $true;
        foreach ($array in $body){
            if (!$first) {
                $params += "&";
            } else {
                $first = $false;
            }
            $params += [System.Web.HttpUtility]::UrlEncode($array[0]) + "=" + [System.Web.HttpUtility]::UrlEncode($array[1]);
        }
        $b = [System.Text.Encoding]::UTF8.GetBytes($params);

        # Use HttpWebRequest instead of Invoke-WebRequest, because the latter doesn't support arrays in POST params.
    $req = [System.Net.HttpWebRequest]::Create($Uri);
    $req.Method = "POST";
    $req.ContentLength = $params.Length;
    $req.ContentType = "application/x-www-form-urlencoded";
    $req.CookieContainer = $WebSession.Cookies

    $str = $req.GetRequestStream();
    $str.Write($b, 0, $b.Length);
    $str.Close();
    $str.Dispose();

    [System.Net.HttpWebResponse] $res = $req.GetResponse();
    $str = $res.GetResponseStream();
    $rdr = New-Object -TypeName "System.IO.StreamReader" -ArgumentList ($str);
    $content = $rdr.ReadToEnd();
    $str.Close();
    $str.Dispose();
    $rdr.Dispose();

    # Build a return object that's similar to a Microsoft.PowerShell.Commands.HtmlWebResponseObject
        $ret = New-Object -TypeName "System.Object";
        $ret | Add-Member -Type NoteProperty -Name "BaseResponse" -Value $res;
        $ret | Add-Member -Type NoteProperty -Name "Content" -Value $content;
        $ret | Add-Member -Type NoteProperty -Name "StatusCode" -Value ([int] $res.StatusCode);
        $ret | Add-Member -Type NoteProperty -Name "StatusDescription" -Value $res.StatusDescription;
        return $ret;
    }
}

$body 参数是这样制作的:

$form=@()
$form+= ,@("value1",'somevalue')
$form+=,@("value2", 'somevalue')
$form+=,@("value2",'somevalue')
$form+=,@("value3",'somevalue')

现在一切看起来都很好。它仍然不起作用,但我原来的唯一键版本也不再起作用了,所以可能还有其他问题。

【讨论】:

  • 它现在可以工作了,我忘记将我的 WebSession 变量设置为全局变量。它昨天工作,因为我在创建函数之前尝试了控制台中的所有内容。之后它仍然处于活动状态,但在重新启动后它当然不是。 #业余
  • 看来原来的 NameValueCollection 解决方案确实有效,而且标题的顺序毕竟不是那么重要。我确实更喜欢我的数组方法:)
猜你喜欢
  • 1970-01-01
  • 2014-05-18
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 2017-04-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多