简体   繁体   中英

Uploading to Artifactory from a Windows Powershell script

I've successfully downloaded a file from Artifactory (Generic Repo) via a WebClient object. I'm having troubles uploading a file via the same method. I'm trying to figure out the simplest method for uploading via Powershell to our server.

Please note that installing other utilities like Curl is not an option at this point. I'm writing automation scripts and want to stick with a basic Windows 2008 r2 server, no installing other utilities since I can't count on them being there across all the servers.

If someone has an example script utilizing the Rest API, that would be perfect!

Example of the download code (this works):

$SOURCE = "https://artifactory.example.com/artifactory/net-generic-local/APP/BF_1.0.zip"  
$DESTINATION = ".\BF_1.0.zip"  
$AF_USER ="user"  
$AF_PWD ="password"  
$WebClient = New-Object System.Net.WebClient  
$WebClient.Credentials = New-Object System.Net.NetworkCredential($AF_USER,$AF_PWD)  
$WebClient.DownloadFile($SOURCE,$DESTINATION)  

This is an example of the upload code (does not work):

$SOURCE = ".\BF_2.0.zip"  
$DESTINATION = "https://artifactory.example.com/artifactory/net-generic-local/APP/BF_2.0.zip"  
$AF_USER ="user"  
$AF_PWD ="password"  
$WebClient = New-Object System.Net.WebClient  
$WebClient.Credentials = New-Object System.Net.NetworkCredential($AF_USER, $AF_PWD)  
$URI = New-Object System.Uri($DESTINATION)  
$WebClient.UploadFile($URI,$SOURCE)  

This is the error I'm getting from the upload:

Exception calling "UploadFile" with "2" argument(s): "The remote server returned an error: (405) Method Not Allowed."  
At E:\transient\af_put.ps1:8 char:1  
+ $WebClient.UploadFile($URI,$SOURCE)  
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException  
    + FullyQualifiedErrorId : WebException  

I tried the Invoke-WebRequest option and was able to get this to work:

$URI = New-Object System.Uri("https://artifactory.example.com/artifactory/net-generic-local/APP/BF_2.0.zip")  
$SOURCE = ".\BF_2.0.zip"  
$AF_USER = "user"  
$AF_PWD = ConvertTo-SecureString "password" -AsPlainText -Force  
$CREDS = New-Object System.Management.Automation.PSCredential ($AF_USER, $AF_PWD)  

Invoke-WebRequest -Uri $URI -InFile $SOURCE -Method Put -Credential $CREDS  

Had to create a PSCrendential object so it would not prompt for the user password. But other then that, this work exactly as I needed.

The reason for your issue is HTTP method used by UploadFile. By default UploadFile uses POST, while to upload file to Artifactory you need to use PUT method. That is why you get 405 "Method Not Allowed" response.

To fix this use UploadFile overload with three parameters like shown here: https://msdn.microsoft.com/en-us/library/ms144230(v=vs.110).aspx

So the correct version of the code will look like:

$SOURCE = ".\BF_2.0.zip"  
$DESTINATION = "https://artifactory.example.com/artifactory/net-generic-local/APP/BF_2.0.zip"  
$AF_USER ="user"  
$AF_PWD ="password"  
$WebClient = New-Object System.Net.WebClient  
$WebClient.Credentials = New-Object System.Net.NetworkCredential($AF_USER, $AF_PWD)  
$URI = New-Object System.Uri($DESTINATION)
$METHOD = "PUT"  
$WebClient.UploadFile($URI, $METHOD, $SOURCE)  

I don't have Artifactory handy, but you might want to try the Invoke-RestMethod PowerShell cmdlet, available in box from PowerShell v3 and higher. Here's a sample of how to do that.

You'll need credentials, and based on their REST documentation, basic authentication of the type we can get with the -Credential param of Invoke-RestMethod should cover us there.

You'll also need to provide a message $body with your request. Look at the JSON sample here from their docs , and then edit the $body I've given as a starting point.

$credential = Get-Credential
$body = @{action="Upload";param2="Data";param3="Data";} | ConvertTo-Json 
Invoke-RestMethod -uri "http://localhost:8080/artifactory/api/build" `
  -ContentType "application/json" -method POST -body $body -Credential

I must say, this is one of the more complex examples of a REST API that I've seen, so to make this easier, I would install curl on a machine and use Fiddler to capture a trace successfully uploading a file. To make things even easier, you could also do this using the Artifactory UI from a browser to upload a file, and simple record a trace of the upload step. Then, grab the JSON in the request and use that as a starting point.

The JFrog knowledgebase offers an example upload to Artifactory via PowerShell . This example uses Invoke-RestMethod as in FoxDeploy's previous answer, but uses an -InFile parameter and a different content type, as follows:

Invoke-RestMethod -uri <complete URI to where the artifact will be in Artifactory>
  -Method Put -InFile <path of file to upload> -Credential <PS creds>
  -ContentType "multipart/form-data" -TimeoutSec <in seconds>

My answer is certainly derivative, but this is what worked for me when pushing something to my Artifactory repo from powershell using an API token for authentication:

$credential_bytes = [System.Text.Encoding]::UTF8.GetBytes($username + ":" + $api_token)
$credentials = [System.Convert]::ToBase64String($credential_bytes)
$credential_header = "Basic " + $credentials    
Invoke-WebRequest -Uri $artifactory_dest_url -InFile "my_file.zip" -Method Put -Headers @{"Authorization"="$credential_header"}

Sigh. I regret that I'm using Powershell. What am I doing with my life? Anyway, it works. Moving on.

Props to FoxDeploy and Maclnos.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM