Skip to content

Instantly share code, notes, and snippets.

@f-steff
Created September 23, 2019 12:02
Show Gist options
  • Save f-steff/67cf974a8ac65dee3153569e10d790b8 to your computer and use it in GitHub Desktop.
Save f-steff/67cf974a8ac65dee3153569e10d790b8 to your computer and use it in GitHub Desktop.
Download all files in a folder on an FTP-server to the DestinationFolder. Source and destination must be specified. UrlPort, UserName and Password can be specified. Defaults to access a hardcoded URL.
# DownloadFtpFolder.ps1 created by f-steff, Sept.12 2019.
# This is a modified version of DownloadFtpDirectory() by Martin Prikryl.
# usage: DownloadFtpFolder.ps1 SourceFolder Destination folder [UrlPort Username Password]
function EnsureTargetDirectory ($localPath)
{
# Ensure to return a full qualified path.
# Will create the folder(s) if needed.
try
{
$VerifiedDirectory = New-Item -ItemType Directory -Path $localPath -ErrorAction stop -Force
}
catch
{
write-host "Error: Destination path could not be created: '$localPath'"
throw "$_"
}
return $VerifiedDirectory.ToString()
}
function DownloadFtpDirectory($url, $credentials, [string]$localPath)
{
# This function is a slightly modified version of Martin Prikryl answer on StackOverflow: https://stackoverflow.com/questions/37080506/powershell-ftp-download-files-and-subfolders
write-debug "localPath = $localPath"
If (!(Test-Path -Path $localPath))
{
throw "Error: Path does not exist: $localPath"
}
write-debug "Source = $url"
write-debug "Destination = $localPath"
$listRequest = [Net.WebRequest]::Create($url)
$listRequest.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails
$listRequest.UsePassive = 1
$listRequest.Credentials = $credentials
$lines = New-Object System.Collections.ArrayList
try
{
$listResponse = $listRequest.GetResponse()
}
catch
{
write-host "Error: Can not access server"
throw ("$_")
}
$listStream = $listResponse.GetResponseStream()
$listReader = New-Object System.IO.StreamReader($listStream)
while (!$listReader.EndOfStream)
{
$line = $listReader.ReadLine()
$lines.Add($line) | Out-Null
}
if ($listReader.PSobject.Properties.Name -contains "Dispose") { $listReader.Dispose() }
if ($listStream.PSobject.Properties.Name -contains "Dispose") { $listStream.Dispose() }
if ($listResponse.PSobject.Properties.Name -contains "Dispose") { $listResponse.Dispose() }
foreach ($line in $lines)
{
$tokens = $line.Split(" ", 9, [StringSplitOptions]::RemoveEmptyEntries)
$name = $tokens[8]
$permissions = $tokens[0]
$localFilePath = Join-Path $localPath $name
$fileUrl = ($url + $name)
if ($permissions[0] -eq 'd')
{
if (!(Test-Path $localFilePath -PathType container))
{
Write-Host "Creating directory $localFilePath"
New-Item $localFilePath -Type directory | Out-Null
}
DownloadFtpDirectory ($fileUrl + "/") $credentials $localFilePath
}
else
{
Write-Host "Downloading $fileUrl to $localFilePath"
$downloadRequest = [Net.WebRequest]::Create($fileUrl)
$downloadRequest.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile
$downloadRequest.Credentials = $credentials
$downloadResponse = $downloadRequest.GetResponse()
$sourceStream = $downloadResponse.GetResponseStream()
$targetStream = [System.IO.File]::Create($localFilePath)
$buffer = New-Object byte[] 10240
while (($read = $sourceStream.Read($buffer, 0, $buffer.Length)) -gt 0)
{
$targetStream.Write($buffer, 0, $read);
}
if ($targetStream.PSobject.Properties.Name -contains "Dispose") { $targetStream.Dispose() }
if ($sourceStream.PSobject.Properties.Name -contains "Dispose") { $sourceStream.Dispose() }
if ($downloadResponse.PSobject.Properties.Name -contains "Dispose") { $downloadResponse.Dispose() }
}
}
}
# Main
$DebugPreference = "Continue" # Display debug
$DebugPreference = "SilentlyContinue" # Suppress debug
try
{
$SourceFolder = If ($($args[0])) { $($args[0]) } Else { throw 'Error: Source folder not specified' } # Opt. Comment during Debugging.
$DestinationFolder = If ($($args[1])) { $($args[1]) } Else { throw 'Error: Destination folder not specified' } # Opt. Comment during Debugging.
# $SourceFolder = '/pub/hvsc/C64Music/DEMOS/Commodore//' # Debug
# $DestinationFolder = 'c:\Work\DownloadFtpFolder\test\' # Debug
$UrlPort = If ($($args[2])) { $($args[2]) } Else { 'arnold.c64.org:21' }
$Username = If ($($args[3])) { $($args[3]) } Else { 'anonymous' }
$PassWord = If ($($args[4])) { $($args[4]) } Else { 'donald@duckburg.com' }
if ($SourceFolder[-1] -ne "/") { $SourceFolder += "/" }
Write-Host ""
Write-Host "Downloading FTP directory using DownloadFtpFolder.ps1"
write-Host "Src = ftp://$UrlPort$SourceFolder"
write-debug "Dst = $DestinationFolder"
write-debug "UrlPort = $UrlPort"
write-debug "Username = $Username"
write-debug "PassWord = $PassWord"
$credentials = New-Object System.Net.NetworkCredential($UserName, $Password)
$url = "ftp://$UrlPort/$SourceFolder"
$VerifiedFolder = EnsureTargetDirectory $DestinationFolder # Ensure we have a full working path.
Write-Host "Dst = $VerifiedFolder"
DownloadFtpDirectory $url $credentials $VerifiedFolder
Write-Host ""
Exit 0
}
catch
{
$line = $_.InvocationInfo.ScriptLineNumber
Write-Host -ForegroundColor Red "ERROR:"
Write-Host -ForegroundColor Red "An exception occurred at line $line"
Write-Host -ForegroundColor Red '$_ = ' $_
Write-Host -ForegroundColor Red '$_.Exception.Message = ' $_.Exception.Message
Write-Host -ForegroundColor Red '$_.GetType().FullName = ' $_.GetType().FullName
Write-Host -ForegroundColor Red '$_.Exception.GetType().FullName = ' $_.Exception.GetType().FullName
Write-Host -ForegroundColor Red '$_.Exception = ' $_.Exception
Write-Host ""
Exit 1
}
@f-steff
Copy link
Author

f-steff commented Sep 23, 2019

Download files from a specified folder loacted an an FTP server.

Requires Jenkins Managed Configuration plugin and the Powershell plugin.

FTP URL and port, as well as username and password are hardcoded in the script, but can be overwritten during invocation.

Instructions for uploading the script.

  1. Upload script to Managed Scripts
  2. Name the script: "DownloadFtpFolder.ps1"
  3. Add a Comment such as "Download all files in a folder on an FTP-server to the DestinationFolder. Source and destination must be specified. UrlPort, UserName and Password can be specified. Defaults to access the HVSC"
  4. Add argument: SourceFolder
  5. Add argument: DestinationFolder
  6. Add argument: [UrlPort]
  7. Add argument: [UserName]
  8. Add argument: [Password]

Instructions for using the script.

  1. Add a Execute managed powershell build step.
  2. Select the script to execute: DownloadFtpFolder.ps1
  3. Select Define arguments:
  4. Set the source folder. - If using together with the List_FTP_Folders.groovy, specify '${MySelectedFolder}'
  5. Set the destination folder: '${WORKSPACE}\HVSC'

Once executed, the files will be downloaded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment