I looked through and tested a few examples I saw online with no success. From what I understand it should look something like the code below:
$hookUrl = 'https://discord.com/api/webhooks/XXXXXXXXXXXXXXXXXXXX'
$Body = @{
'username' = $env:username
'content' = "this is a test"
"file=@C:\Users\User\Desktop\test.txt"
}
Invoke-WebRequest -uri $hookUrl -Method POST -Body $Body -Headers @{'Content-Type' = 'application/json'}
ERRORS
Invoke-WebRequest : {"code": 50109, "message": "The request body contains invalid JSON."}
At line:11 char:1
Invoke-WebRequest -uri $hookUrl -Method POST -Body $Body -Headers @{' ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
I have seen a few extensively long methods to achieve this in the documentation, however if you see below I will post a one liner that accomplishes what I want using CMD. Is it really this simple in CMD but in powershell it takes 15 lines?
curl -F "payload_json={\"username\": \"jakoby\", \"content\": \"download me\"}" -F "file=@\"C:\Users\User\Desktop\newUser.txt\"" WEB-HOOK
CodePudding user response:
Update:
The answer below (next section) addresses the original form of your question.
It later emerged that you're looking for the PowerShell equivalent of a
curl
command line that uses amultipart/form-data
submission to submit both JSON and upload a local file.Example 5 in the
Invoke-WebRequest
help topic shows you to do that, but it is much more verbose than thecurl
command.The simplest solution may therefore be to simply call your
curl
command from PowerShell, but be sure to usecurl.exe
to unambiguously target the external executable, not thecurl
alias forInvoke-WebRequest
that is built into Windows PowerShell (it has been removed in PowerShell (Core) 7 ).curl.exe -F "payload_json={\`"username\`": \`"jakoby\`", \`"content\`": \`"download me\`"}" -F "file=@\`"C:\Users\User\Desktop\newUser.txt\`"" WEB-HOOK
- Note the unfortunate need to escape the embedded
"
twice:- Once, with
`
, to satisfy PowerShell's syntax requirements for double-quoted strings (as expected).- You could obviate the need for this if you used
'...'
for the overall quoting, but that would preclude embedding variable values directly in the string.
- You could obviate the need for this if you used
- Unexpectedly again, with
\
, to work around a long-standing bug with respect to passing arguments containing verbatim"
chars. to external programs, still present as of PowerShell 7.2.x - see this answer.
- Once, with
- Note the unfortunate need to escape the embedded
Since the target web service expects JSON, you must convert your $Body
hashtable to JSON before passing it to Invoke-WebRequest
's -Body
parameter, which you can do with ConvertTo-Json
:
Invoke-WebRequest -uri $hookUrl -Method POST -Body (ConvertTo-Json $Body) -Headers @{'Content-Type' = 'application/json'}
The obligatory general caveat: with more deeply nested objects, you may need to pass a -Depth
argument to ConvertTo-Json
to prevent accidental truncation of data - see this post.
It seems that you also want to upload a local file:
Since the web service has no access to your local file system, passing a local file path as part of your JSON cannot work - the local file's content must be uploaded.
The
Invoke-WebRequest
docs only discuss uploading local files in the context ofmultipart/form-data
submissions - see example 5, for instance.