2

I have a Jenkins Job that requires a file as parameter (I'm using the file parameter plugin). When I made the call to Jenkins I notice that the file parameter doesn't get sent but the other parameters do (CHOICE and string), what I'm doing wrong?

$credPair = "user:token";
$encodedCredentials = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($credPair));
$headers = @{
    "Authorization" = "Basic $encodedCredentials";
    "Content-Type" = "multipart/form-data";
}

$choiceParam = "option"
$stringParam = "value"
$file = "file_path"
$Body = @{ "File" = [IO.File]::ReadAllText($file); }

$url = "https://server/job/buildWithParameters?CHOICE=" + $choiceParam + '&string' + $stringParam

try {
    Invoke-RestMethod -Uri $url -Headers $headers -Method Post -Body $Body
}
catch {
    Write-Host "StatusCode: " $_.Exception.Response.StatusCode.value__
    Write-Host "StatusDescription: " $_.Exception.Response.StatusDescription
    write-host "Error details: " $_.ErrorDetails.Message
    exit
}

I already tried the next questions and didn't work multipart/form-data file upload with PowerShell powershell invoke-restmethod multipart/form-data How to send multipart/form-data with PowerShell Invoke-RestMethod Using PowerShell Invoke-RestMethod to POST large binary multipart/form-data

I want to send a file parameter to Jenkins via HTTP Post Request with PowerShell

  • 1
    I think you might want ```-Form``` instead of ```-Body``` (and remove the ```Content-Type``` header as ```-Form``` will set this for you) - see https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-restmethod?view=powershell-7.3#-form (assuming you're using pwsh.exe rather than powershell.exe) – mclayton Mar 29 '23 at 21:29
  • A MIME attachment is added to the body of a http request. Each attachment starts with two dashes on a new line. See following sample : https://learn.microsoft.com/en-us/previous-versions/office/developer/exchange-server-2010/aa563375(v=exchg.140) – jdweng Mar 29 '23 at 22:09

2 Answers2

1

@zett42 I solve it, apparently only in the form you put the file, the others params are put in the url

$credPair = "user:token";
$encodedCredentials = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($credPair));
$headers = @{
    "Authorization" = "Basic $encodedCredentials";
}

$choiceParam = "option"
$stringParam = "value"
$file = "file_path"

$form = @{
    INSERT_NAME_OF_FILE_PARAM = Get-Item $file
}

$url = "https://server/job/INSERT_JOBNAME/buildWithParameters?INSERT_NAME_OF_CHOICE_PARAM=" + $choiceParam + '&INSERT_NAME_OF_STRING_PARAM=' + $stringParam

try {
    Invoke-RestMethod -Uri $url -Headers $headers -Method Post -Form $form
}
catch {
    Write-Host "StatusCode: " $_.Exception.Response.StatusCode.value__
    Write-Host "StatusDescription: " $_.Exception.Response.StatusDescription
    write-host "Error details: " $_.ErrorDetails.Message
    exit
}
  • Thanks for sharing your findings. I've linked my answer to yours and added a note that mine only works for freestyle jobs. – zett42 Mar 30 '23 at 17:14
0

Note: As it turns out, the solution below only works for freestyle jobs. If you need a solution for pipeline jobs, you may use this solution (which requires the file parameter plugin).


I have used Invoke-RestMethod with parameter -Form to upload files to Jenkins successfully.

Something like that should work:

$credPair = "user:token";
$encodedCredentials = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($credPair));
$headers = @{
    "Authorization" = "Basic $encodedCredentials";
    # NOTE: no Content-Type header, Invoke-RestMethod adds it automatically when using -Form
}

$choiceParam = "option"
$stringParam = "value"
$file = "file_path"

$form = @{
   json = ConvertTo-Json -Compress @{
       parameter = @(
           @{ name = "INSERT_NAME_OF_CHOICE_PARAM"; value = $choiceParam }
           @{ name = "INSER_NAME_OF_STRING_PARAM"; value = $stringParam }

           # IMPORTANT: value of file must be equal to file key used to assign FileInfo below
           @{ name = "INSERT_NAME_OF_FILE_PARAM"; file = "file1" }
       )
   }

   # Don't read the file on your own, Invoke-RestMethod will do it
   file1 = [IO.FileInfo] $file
}

# NOTE: /build instead of /buildWithParameters
$url = "https://server/job/INSERT_JOBNAME/build"

try {
    Invoke-RestMethod -Uri $url -Headers $headers -Method Post -Form $form
}
catch {
    Write-Host "StatusCode: " $_.Exception.Response.StatusCode.value__
    Write-Host "StatusDescription: " $_.Exception.Response.StatusDescription
    write-host "Error details: " $_.ErrorDetails.Message
    exit
}

For reference, I got the basic principle for uploading files to a Jenkins job from this answer.

zett42
  • 25,437
  • 3
  • 35
  • 72
  • Hi @zett42, I tried your code but it give a 500 error, this is the message: Skip to contentManaged ControllerDashboard Oops!A problem occurred while processing the request.Logging ID=f9ac9750-4e60-4286-b092-dc24213c9558JenkinsREST APICloudBees CI Managed Controller 2.361.3.2-rollingDocumentationKnowledgeBasewww.cloudbees.com. – milk_away.89 Mar 30 '23 at 14:31
  • @milk_away.89 Did you put the job name into the URL? It should look like `https://server/job/INSERT_JOBNAME/build`. Also I've used placeholders for the job parameter names, which you should replace by the actual parameter names. – zett42 Mar 30 '23 at 15:33
  • Yes, I put the job name in the URL. Can be the way the form is formatted? – milk_away.89 Mar 30 '23 at 15:35
  • @milk_away.89 I've found a mistake, see update. `@{ name = "INSERT_NAME_OF_FILE_PARAM"; file = "file1" }` – zett42 Mar 30 '23 at 15:38
  • I still get the same, the file I'm trying to send is yaml, does that affect on something? – milk_away.89 Mar 30 '23 at 15:46
  • @milk_away.89 File type shouldn't be relevant, I've even send large binary files like this. – zett42 Mar 30 '23 at 15:52
  • Also I use the file parameter plugin which I think is base64, doesn't that affect on something as well? – milk_away.89 Mar 30 '23 at 15:57
  • @milk_away.89 Found another mistake, see update. Forgot `ConvertTo-Json`. Sorry for the stitchwork, my actual script is more complicated, but I couldn't post it because it's written at my workplace. – zett42 Mar 30 '23 at 15:57
  • @milk_away.89 This code works with the built-in file parameter type. I don't know about file parameter plugin. Why do you need it? – zett42 Mar 30 '23 at 15:59
  • Because I was unable to use it in the Jenkins pipeline but I think that could be the issue – milk_away.89 Mar 30 '23 at 16:02
  • @milk_away.89 Sorry, can't help you with file parameter plugin, I haven't used it. Now that you wrote that, I think the code was used for uploading files to a freestyle job only. – zett42 Mar 30 '23 at 16:06
  • @milk_away.89 Please post link to file parameter plugin, maybe I can figure something out. – zett42 Mar 30 '23 at 16:12
  • don't worry, you help me a lot actually, thank you – milk_away.89 Mar 30 '23 at 16:13
  • 1
    So sorry I didn't see the message where you ask me to post a link of the file parameter plugin, but I was able to solve it, thanks – milk_away.89 Mar 30 '23 at 16:34