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
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 a multipart/form-data
submission to submit both JSON and upload a local file.
Example 6 in the Invoke-WebRequest
help topic shows you how to do that, but it is more verbose than the curl
command.
The simplest solution may therefore be to simply call your curl
command from PowerShell, but be sure to use curl.exe
to unambiguously target the external executable, not the curl
alias for Invoke-WebRequest
that is built into Windows PowerShell (it has been removed in PowerShell (Core) 7+).
# In PowerShell 7.3+, the "\" chars. are *no longer necessary*.
curl.exe -F "payload_json={\`"username\`": \`"jakoby\`", \`"content\`": \`"download me\`"}" -F "file=@\`"C:\Users\User\Desktop\newUser.txt\`"" WEB-HOOK
"
twice:
`
, to satisfy PowerShell's syntax requirements for double-quoted strings (as expected).
'...'
for the overall quoting, but that would preclude embedding variable values directly in the string.\
, to work around a long-standing bug with respect to passing arguments containing verbatim "
chars. to external programs.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 of multipart/form-data
submissions - see example 6, for instance.