如何通过网络请求传递数组 [英] How to pass an array via web-request

查看:17
本文介绍了如何通过网络请求传递数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

情况:

我们会自动从某些网络服务(每晚运行的 PowerShell 脚本)收集许多报告,并且每天以手动模式(在网络表单上拖放)这些报告都会加载到我们的数据库中.

We collect automatically many reports from some web services (PowerShell script running every night), and every day in manual mode (drag and drop on web-form) this reports are loaded in our DB.

现在我们的 IT 部门为我们提供了一个 API,无需用户交互即可处理这项工作.

Now our IT department gave us an API that can handle this job without user interaction.

问题:

正如在求职信(关于这个 API)中所写的那样,它等待带有文件的 reports[n] 数组.可以用 PHP 和 curl 来完成:

As was written in covering letter (about this API) it waits for reports[n] array with file. It can be done with PHP and curl:

$report = 'report_20160825.{8302F59C-E1E4-410F-BE37-A24CCD7E515E}.zip';
$cfile = new CURLFile(realpath($report),'application/zip',$report);
$PostData = array("reports[0]"=>$cfile);

但是如何通过 PowerShell 发送名为 reports[n] 的数组?

But how to send array named reports[n] via PowerShell?

我尝试过的:

$url = "https://test.example.com/uploadAPI/upload.php"
$Source =  "D:\report_20160825.{8302F59C-E1E4-410F-BE37-A24CCD7E515E}.zip"
$contentType = "multipart/form-data"

$Username = "ApiUploadKey"
$Headers = @{Authorization="Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:" -f $Username)))}

$FileContens = get-content $Source
$PostData = @{"reports[0]" = $FileContens;} 
#$reports = @($FileContens,'application/zip',$Source)

(Invoke-WebRequest -uri $url -Method POST -Headers $Headers -Body $PostData -ContentType $contentType).Content

#Invoke-RestMethod -uri $url -Method POST -Headers $Headers -Body $PostData -ContentType $contentType

这给了我一个回应,我正在通过not-a-report.

That gives me a response that I am passing not-a-report.

编辑 2016-10-11

进一步调查让我看到这个答案和这个文章.我尝试使用 boundary:

Further investigation bring me to this answer and this article. I tried to use boundary:

clear
$url = "https://test.example.com/uploadAPI/upload.php"
$filename = "report_20160825.{8302F59C-E1E4-410F-BE37-A24CCD7E515E}.zip"
$Source =  "D:\"+$filename

$Username = "ApiUploadKey"
$Headers = @{Authorization="Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:" -f $Username)))}

$FileContens = get-content $Source
$enc = [System.Text.Encoding]::GetEncoding("iso-8859-1")
$fileBin = [IO.File]::ReadAllBytes($Source)
$fileEnc = $enc.GetString($fileBin)


$boundary = [System.Guid]::NewGuid().ToString()

$LF = "`n"

$contentType = "multipart/form-data; boundary=--$boundary"
#$bodyLines = "--"+$boundary+$LF+"Content-Disposition: form-data; name=`"reports[]`"; filename=`""+$filename+"`""+$LF+$LF+"Content-Type: application/zip"+$LF+"--"+$boundary+"--"+$LF+$LF+$FileContens+$LF+"--"+$boundary

$bodyLines = (
    "--$boundary",   #I have tried reports[0] here too
    "Content-Disposition: form-data; name=`"reports[]`"; filename=`"$filename`"",   # filename= is optional
    "Content-Type: application/zip",
    "",
    #$FileContens,
    $fileEnc,
    "--$boundary--"
    ) -join $LF


try {

    #Invoke-WebRequest -Uri "https://asrp.cntd.ru/uploadAPI/" -Headers $Headers -WebSession $ws
    Invoke-RestMethod  -Uri $url -Body $bodyLines -Method POST -Headers $Headers -ContentType $contentType -TimeoutSec 50
}
catch [System.Net.WebException] {
    Write-Error( "FAILED to reach '$url': $_" )
    throw $_
}

但结果相同.

我也试过这个:

$wc = new-object System.Net.WebClient
$wc.Credentials = new-object System.Net.NetworkCredential("ApiUploadKey","")

ls "D:\*.zip" | foreach { 
    $wc.UploadFile('https://test.example.com/uploadAPI/upload.php', $_.FullName )
    write-host $_.FullName
}

答案中的另一种解决方案:

Invoke-RestMethod -Uri $url -InFile $Source -ContentType "multipart/form-data" -Method POST -Headers $Headers

总是相同的回复 - 不是报告

编辑 2016-10-17

卷曲

我已经为 Windows 下载了 curl.并像这样使用它:

I have downloaded curl for windows. And use it like:

curl.exe https://test.example.com/uploadAPI/upload.php --user ApiUploadKey: --form "reports[0]=@d:\report_746_226255_20161010_1635.zip;type=application/zip"

这给了我:

[{"code" : 102 , "guid" : "{23CE9F7F-BEC8-4D4C-8AC3-2865CFA94FBD}" , "id" : "5804902bc73a2475177464", "filename" : "report_746_226255_20161010_1635.zip"}]

所以使用 curl 可以正常工作!

So with curl it works fine!

小提琴手

不知道要发布什么日志.

Don't know exactly what log to post.

当我像这样发送文件时:

When I send file like this:

POST https://test.example.com/uploadAPI/upload.php

Content-Type: multipart/form-data; boundary=-------------------------acebdf13572468
User-Agent: Fiddler
Host: test.example.com
Authorization: Basic ...
Content-Length: 21075175

请求正文:

---------------------------acebdf13572468
Content-Disposition: form-data; name="reports[]"; filename="report_746_226254_20161010_1320.{B67A9D89-368B-4665-96AC-77C2CA0F4766}.zip"
Content-Type: application/zip

<@INCLUDE *D:\report_746_226254_20161010_1320.{B67A9D89-368B-4665-96AC-77C2CA0F4766}.zip*@>
---------------------------acebdf13572468--

我得到了

HTTP/1.1 200 OK
Date: Mon, 17 Oct 2016 10:04:43 GMT
Server: Apache/2.4.20 (Win64) OpenSSL/1.0.2h PHP/7.0.6
X-Powered-By: PHP/7.0.6
Set-Cookie: SESSION_UPLOAD_ID=.....; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Connection: close
Content-Length: 193
Content-Encoding: none
Accept-Ranges: bytes
Content-Type: text/html; charset=UTF-8

[{"code" : 102 , "guid" : "{B67A9D89-368B-4665-96AC-77C2CA0F4766}" , "id" : "5804a23be4152532018928", "filename" : "report_746_226254_20161010_1320.{B67A9D89-368B-4665-96AC-77C2CA0F4766}.zip"}]

推荐答案

PHP 代码使用 Curl 类并将 $PostData 设置为:

The PHP code use Curl class and set $PostData as:

 $PostData = array("reports[0]"=>$cfile);

$PostData 是一个键/值对数组(在 PHP 中),键名为 Reports[0].它只是一个表示键的字符串名称,而不是数组元素.

$PostData is an array of key/value pair (in PHP), and the key is named Reports[0]. it's just a string name represent the key not an array element.

在 curl 命令行工具中,我们可以使用以下命令上传文件:

in curl commandLine tool we can upload file with the command:

 curl.exe   -F Reports[0]=@"I:\test\report_20160825.{8302F59C-E1E4-410F-BE37-A24CCD7E515E}.zip"  http://MyServer/uploader/api/upload

或者,它可能是(注意关键的 Reports[0][2][3] ):

or, it may be (note the key Reports[0][2][3] ):

   curl.exe   -F Reports[0][2][3]=@"I:\test\report_20160825.{8302F59C-E1E4-410F-BE37-A24CCD7E515E}.zip"  http://asd-pc/uploader/api/upload

-F 用于输入表单键/值对在文件名前注意@在您的服务器中尝试并在 Fiddler 中查看会话以了解 curl 和 PHP 如何将请求发送到服务器.

-F is for entering Form key/value pair Note @ before filename Try it in your server and view the session in Fiddler to know how curl and PHP send the request to the server.

您可以为具有其他键名的其他文件传递其他参数,例如 -H(标题)-v(详细)-F,例如 Reports1.

You can pass other parameters like -H (header) -v (verbose) -F for other files with other key name e.g Reports1.

我使用运行 Web Api2 服务的 Web 服务器测试了此代码,该服务将文件上传到服务器并且运行良好.

I tested this code with My web server running Web Api2 service that upload file to the server and it's running fine.

所以,问题是:如何转换该代码以使用 Powershell.

So, the problem is: how to convert that code to work with Powershell.

在 PHP 或命令行工具 curl 中,它会自动为支持 Multipart/form-data 的文件上传准备 Header 和 Request Body.

In curl either PHP or commandLine tool , it auto prepare the Header and the Request Body for file uploading that support Multipart/form-data.

Powershell 命令:Invoke-WebRequest 和 Invoke-RestMethod 都不知道如何格式化请求正文以符合 RFC 中给出的 Multipart/form-data 标准 表单:multipart/form-data

Both Powershell commands: Invoke-WebRequest and Invoke-RestMethod are unaware on how to format the request body in order to comply to the standard of Multipart/form-data as given in the RFC Forms: multipart/form-data

您必须手动设置消息正文,然后调用您的电话

You have to manually set the message body and then invoke your call

以下脚本使用 powershell 将文件上传到 Web 服务器.

The following script Upload file to web server using powershell.

我设置了 Content-Type: application/octet-stream 以支持任何类型,包括 zip 文件.

I set Content-Type: application/octet-stream to support any type including zip files.

    function Upload-File ( $InFile,$Uri    )
    {    
        $Username = "ApiUploadKey"
        $Headers = @{Authorization="Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:" -f $Username)))}
        $LF = "`n"   
        $fileName = Split-Path $InFile -leaf
        $boundary = [System.Datetime]::Now.Ticks.ToString()
        $binaryData = [System.IO.File]::ReadAllBytes($InFile)   
        $binaryEncoded=[System.Text.Encoding]::GetEncoding("iso-8859-1").GetString($binaryData) 
        $ContentType = "application/octet-stream" 

        $body = @"
    --$boundary
    Content-Disposition: form-data; name=`"Reports[0]`"; filename=`"$fileName`"
    Content-Type: $ContentType
    $LF
    $binaryEncoded
    --$boundary--
    $LF
    "@  

        try
        { 

          return Invoke-RestMethod -Uri $Uri -Method Post -ContentType "multipart/form-data; boundary=$boundary"   -Body $body -Headers $Headers                             

        }
        catch [Exception]
        {
            $PSCmdlet.ThrowTerminatingError($_)
        }
    }


    #--   test the function ---------------------------------
    cls
    $uri = "http://MyServer/uploader/api/upload"        
    $filePath = "I:\test\report_20160825.{8302F59C-E1E4-410F-BE37-A24CCD7E515E}.zip"
    $response = Upload-File -InFile $filePath -Uri $uri  #-Credential $credentials
    $response

来自 fiddler 的输出会话

The output session from fiddler

    POST http://MyServer/uploader/api/upload HTTP/1.1
    Authorization: Basic QXBpVXBsb2FkS2V5Og==
    User-Agent: Mozilla/5.0 (Windows NT; Windows NT 6.1; en-US) WindowsPowerShell/5.0.10586.117
    Content-Type: multipart/form-data; boundary=636123339963709320
    Host: MyServer
    Content-Length: 379
    Connection: Keep-Alive

    --636123339963709320
    Content-Disposition: form-data; name="Reports[0]"; filename="report_20160825.{8302F59C-E1E4-410F-BE37-A24CCD7E515E}.zip"
    Content-Type: application/octet-stream


    xxxxxxxxxxxxxxxxxxxxxxxxxxxStream of byte sxxxxxxxxxxxxxxx

在上面的会话数据中,您可以看到 Reports[0] 的标题 名称

In the session data above you see Reports[0] is titled name

您可以在命令中使用相同的代码:Invoke-WebRequest

You can use the same code with the command: Invoke-WebRequest

这篇关于如何通过网络请求传递数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆