我正在开发一个powershell脚本,它应该使用HTTP POST方法调用REST API。 REST API用于从外部备份文件还原特定于应用程序的备份资源。表单数据中备份文件的KeyName必须是" backupFile"。 内容类型是multipart / form-data。这就是我在做的事情:
function invoke-rest {
param([string]$uri)
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
#$enc = [system.Text.Encoding]::UTF8
$request = [System.Net.HttpWebRequest]::Create($uri)
$request.Credentials = New-Object system.net.networkcredential("user","password")
$request.CookieContainer = New-Object System.Net.CookieContainer
$request.AllowWriteStreamBuffering = $true;
$boundary = "--------------"+(get-date -format yyyymmddhhmmss).ToString()
$header = "--"+$boundary
$body = $header + "`r`n" +"Content-Disposition: form-data; name='backupFile'; filename='somefile.sql.gz'"+"`r`n" + "Content-Type: multipart/form-data"+"`r`n`r`n"
$body = $body + [System.Text.Encoding]::UTF8.GetString($(Get-Content 'somefile.sql.gz' -Encoding byte)) + "`r`n"
$footer = $header+"--"
$body = $body + $footer
$bytes = [System.Text.Encoding]::UTF8.GetBytes($body)
$request.ContentType = "multipart/form-data; boundary="+$boundary
$request.Method = "Post"
$request.keepAlive = $true
$request.ContentLength = $bytes.Length
$requestStream = $request.GetRequestStream()
$requestStream.Write($bytes,0,$bytes.length);
$requestStream.Flush();
$requestStream.Close();
$response = $request.GetResponse()
$responseStream = $response.GetResponseStream()
$stream = new-object System.IO.StreamReader $responseStream
$xmlDump = $stream.ReadToEnd()
$output = [xml]$xmlDump
$response.close()
return $output
}
$uri = "http://localhost/rest/backups"
invoke-rest $uri
抛出错误: REST请求失败,必须存在名为backupFile的数据表单,返回:错误请求(400)
我在这里做错了什么?
答案 0 :(得分:2)
在这种情况下,400可能意味着在生成
时出现了错误文件是您需要在请求中提交的唯一参数吗?如果是这样,您可以使用WebClient.UploadFile API并让它处理生成大部分请求。
$client = New-Object System.Net.WebClient
$client.Credentials = $creds
$client.UploadFile('http://localhost/rest/backups', 'c:\temp\somefile.sql.gz')
如果您确实需要在mime多部分请求中提交多个参数,那么您就会看到一个痛苦的世界。我自己必须通过PowerShell做到这一点,而且根本不开心,特别是当你开始涉及二进制数据时。经过多次挫折之后headbanging,我最终得到以下内容来转换值的哈希表并输出一个多部分。抱歉,我无法确切地发现您的代码存在什么问题,但也许这可能会直接为您工作,或者引导您确定您的问题所在。
function ConvertTo-MimeMultiPartBody
{
param(
[Parameter(Mandatory=$true)]
[string]$Boundary,
[Parameter(Mandatory=$true)]
[hashtable]$Data
)
$body = '';
$Data.GetEnumerator() |% {
$name = $_.Key
$value = $_.Value
$body += "--$Boundary`r`n"
$body += "Content-Disposition: form-data; name=`"$name`""
if ($value -is [byte[]]) {
$fileName = $Data['FileName']
if(!$fileName) {
$fileName = $name
}
$body += "; filename=`"$fileName`"`r`n"
$body += 'Content-Type: application/octet-stream'
#ISO-8859-1 is only encoding where byte value == code point value
$value = [System.Text.Encoding]::GetEncoding("ISO-8859-1").GetString($value)
}
$body += "`r`n`r`n"
$body += $value
$body += "`r`n"
}
$body += "--$boundary--"
return $body
}