curl powershell调用-剩余方法多部分/表单-数据

kzmpq1sx  于 2022-11-13  发布在  Shell
关注(0)|答案(8)|浏览(142)

我目前正在尝试使用REST API将文件上传到Web服务器。如前所述,我使用PowerShell来完成此操作。使用curl,这没有问题。调用如下所示:

curl -H "Auth_token:"$AUTH_TOKEN -H "Content-Type:multipart/form-data" -X POST -F appInfo='{"name": "test","description": "test"}' -F uploadFile=@/test/test.test https://server/api/

但是当我使用Invoke-Restmethod命令将其导出到powershell时,我完全无能为力。就我所搜索的而言,不可能使用Invoke-Restmethod来导出此文件。https://www.snip2code.com/Snippet/396726/PowerShell-V3-Multipart-formdata-example但即使使用了Snipped,我也没有足够的智慧来使其工作,因为我不想上传两个文件,而是上传一个文件和一些参数。
如果有人能用这个让我重回正轨,我将非常感谢:o谢谢!

zaqlnxep

zaqlnxep1#

@Bacon-Bits的答案似乎对我不起作用。我的服务器拒绝了它,并返回了一个可能格式错误的表单数据主体:-(
我找到了this gist,并根据我的目的对它进行了一些修改。

$FilePath = 'c:\temp\temp.txt';
$URL = 'http://your.url.here';

$fileBytes = [System.IO.File]::ReadAllBytes($FilePath);
$fileEnc = [System.Text.Encoding]::GetEncoding('UTF-8').GetString($fileBytes);
$boundary = [System.Guid]::NewGuid().ToString(); 
$LF = "`r`n";

$bodyLines = ( 
    "--$boundary",
    "Content-Disposition: form-data; name=`"file`"; filename=`"temp.txt`"",
    "Content-Type: application/octet-stream$LF",
    $fileEnc,
    "--$boundary--$LF" 
) -join $LF

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

yptwkmov2#

它应该是非常简单的。从this answer

$Uri = 'https://server/api/';
$Headers = @{'Auth_token'=$AUTH_TOKEN};
$FileContent = [IO.File]::ReadAllText('C:\test\test.test');
$Fields = @{'appInfo'='{"name": "test","description": "test"}';'uploadFile'=$FileContent};

Invoke-RestMethod -Uri $Uri -ContentType 'multipart/form-data' -Method Post -Headers $Headers -Body $Fields;

如果文件不是文本文件,则可能需要使用[IO.File]::ReadAllBytes()
如果你上传的是一个巨大的文件,这也可能不会很好地工作。

fcg9iug3

fcg9iug33#

对于PowerShell Core,使用新的-Form参数即可实现这一点。
请参阅:https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-restmethod?view=powershell-7

$Uri = 'https://api.contoso.com/v2/profile'
$Form = @{
    firstName  = 'John'
    lastName   = 'Doe'
    email      = 'john.doe@contoso.com'
    avatar     = Get-Item -Path 'c:\Pictures\jdoe.png'
    birthday   = '1980-10-15'
    hobbies    = 'Hiking','Fishing','Jogging'
}
$Result = Invoke-RestMethod -Uri $Uri -Method Post -Form $Form
cygmwpex

cygmwpex4#

我需要同时传递头和一些参数(insert=truedebug=true)沿着文件内容。

param([string]$path)

$Headers = @{Authorization = "Bearer ***************"}
$Uri = 'https://host:8443/api/upload'

$fileBytes = [System.IO.File]::ReadAllBytes($path);
$fileEnc = [System.Text.Encoding]::GetEncoding('ISO-8859-1').GetString($fileBytes);
$boundary = [System.Guid]::NewGuid().ToString(); 
$LF = "`r`n";

$bodyLines = ( 
    "--$boundary",
    "Content-Disposition: form-data; name=`"insert`"$LF",
    "true$LF",
    "--$boundary",
    "Content-Disposition: form-data; name=`"debug`"$LF",
    "true$LF",    
    "--$boundary",
    "Content-Disposition: form-data; name=`"file`"; filename=`"$path`"",
    "Content-Type: application/octet-stream$LF",
    $fileEnc,
    "--$boundary--$LF" 
) -join $LF

Invoke-RestMethod -Uri $Uri -Headers $Headers -Method Post -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $bodyLines
x3naxklr

x3naxklr5#

所以,我最近一直在努力解决这个问题,发现确实有可能匹配curl功能,但是如何正确地处理multipart/form-data还不是很明显。上面的所有回答都涵盖了这个难题的重要部分,但是我将在这里尝试把它们联系在一起,以供下一个试图在原生Powershell中实现curl功能的遗憾的家伙使用。
@jklemmack的解决方案使我走上了正确的道路,而且是最灵活的,因为它允许您具体地构造表单数据内容,控制边界沿着如何在其中格式化数据。
对于任何尝试这样做的人来说,我认为重要的是,您要为自己配备一个适当的Web调试代理,如Fiddler(.net)或Burp Suite(java),这样您就可以详细检查每个REST调用,以了解传递到API的数据的特定格式。
在我的具体例子中,我注意到curl在表单数据的每个部分上方插入了一个空行--因此,要扩展@jklemmack的示例,它看起来如下所示:

$bodyLines = (
        "--$boundary",
        "Content-Disposition: form-data; name=`"formfield1`"",
        '',
        $formdata1,
        "--$boundary",
        "Content-Disposition: form-data; name=`"formfield2`"",
        '',
        $formdata2,
        "--$boundary",
        "Content-Disposition: form-data; name=`"formfield3`"; filename=`"$name_of_file_being_uploaded`"",
        "Content-Type: application/json",
        '',
        $content_of_file_being_uploaded,
        "--$boundary--"
    ) -join $LF

希望这能在将来为某人节省很多时间!
我也仍然同意,如果您需要从头开始执行此操作,并且可以选择直接使用curl原生二进制文件(同时确保对安全性和合规性的尽职调查),利用它的成熟性和它提供的便利性。使用curl。最好由curl社区对这种多部分逻辑进行全面的测试和维护,而不是由您的内部开发或运营团队承担责任。

zour9fqk

zour9fqk6#

  • 有很多的黑客代码需要做这一点,这里的大多数答案只是陈述他们。这些答案应该要么删除或存档沿着所有的黑客博客在互联网上。*

使用最新版本(撰写本文时为PowerShell Core v7.2.6)。您所需要的只是使用Get-Item-Path给予路径。

$Form = @{ 
        document=  Get-Item -Path .\image.png # no leading @ sign.
    }    

  $Result = Invoke-RestMethod -Uri $Uri -Method Post -Form $Form

请注意,在get item之前没有@符号,就像您在curl中输入一样。我输入了@符号,破坏了我的请求。

参考:https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-restmethod?view=powershell-7#example-4--simplified-multipart-form-data-submission

5ktev3wc

5ktev3wc7#

我在尝试使用Invoke-RestMethod执行以下curl命令时遇到了一些问题:

curl --request POST \
  --url https://example.com/upload_endpoint/ \
  --header 'content-type: multipart/form-data' \
  --form 'file=@example.csv'
  -v

在我的例子中,事实证明使用curl和powershell更容易。

$FilePath = "C:\example.csv"
$CurlExecutable = "C:\curl-7.54.1-win64-mingw\bin\curl.exe"

$CurlArguments = '--request', 'POST', 
                'https://example.com/upload_endpoint/',
                '--header', "'content-type: multipart/form-data'",
                '--form', "file=@$FilePath"
                '-v',

# Debug the above variables to see what's going to be executed
Write-Host "FilePath" $FilePath
Write-Host "CurlExecutable" $FilePath
Write-Host "CurlArguments" $CurlArguments

# Execute the curl command with its arguments
& $CurlExecutable @CurlArguments

curl's website上下载操作系统的可执行文件。
以下是一些 * 可能 * 让您选择curl而不是powershell的invoke-restmethod的原因

  • 许多工具都可以生成curl命令
  • curl支持上传大于2GB的文件(参见Shukri亚当斯的评论)

Curl和Powershell的invoke-restmethod都是很好的解决方案。如果其他解决方案都不适合你,你可能要考虑curl。通常坚持使用内置解决方案会更好,但有时替代方案也会很有用。

1hdlvixo

1hdlvixo8#

这样的痛苦试图得到一个powershell v4的windows 8. 1上传文件到我的upload.php

# This code works and matches to a Firefox 78.6.0esr upload transmission verified via wireshark

$FilePath = 'c:\Temp\file-to-upload.txt';
$URL = 'http://127.0.0.1/upload.php';

$fileBytes = [System.IO.File]::ReadAllBytes($FilePath);
$fileEnc = [System.Text.Encoding]::GetEncoding('UTF-8').GetString($fileBytes);
$boundary = [System.Guid]::NewGuid().ToString(); 
$LF = "\r\n";

$bodyLines = "--$boundary $LF Content-Disposition: form-data; name='file'; filename='file-to-upload.txt' $LF Content-Type: application/octet-stream $LF $fileEnc $LF --$boundary-- $LF";

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

作为参考,upload.php是:

<?php
    $uploaddir = '/var/www/uploads/';
    $uploadfile = $uploaddir . $_FILES['file']['name'];
    move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)
?>

Wireshark示例

POST /upload.php HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 6.3; en-US) WindowsPowerShell/4.0
Content-Type: multipart/form-data; boundary=96985b62-451a-41fa-9eca-617e3599797c
Host: 127.0.0.1
Content-Length: 284
Connection: Keep-Alive

--96985b62-451a-41fa-9eca-617e3599797c \r\n Content-Disposition: form-data; name='file'; filename='ftp.txt' \r\n Content-Type: application/octet-stream \r\n open 127.0.0.1 21
anonymous
anonymous
bin
put file-to-upload.txt
quit
 \r\n --96985b62-451a-41fa-9eca-617e3599797c-- \r\nHTTP/1.1 200 OK
Date: Sat, 02 Jan 2021 22:11:03 GMT
Server: Apache/2.4.46 (Debian)
Content-Length: 0
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

相关问题