Created
September 27, 2016 06:04
-
-
Save FeodorFitsner/7016cc13bc91db525331bda55c232ed1 to your computer and use it in GitHub Desktop.
Parallel copying over FTP with WinSCP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param ( | |
$sessionUrl = "ftp-host-name", | |
$username = "your-username", | |
$password = "your-password", | |
$remotePath = "/", | |
$localPath = "C:\projects\...", | |
$batches = 20 | |
) | |
# Event handling function | |
function FileTransferred { | |
param($e) | |
if ($e.Error -eq $Null) | |
{ | |
#Write-Host ("Transfer of {0} succeeded" -f $e.FileName) | |
} | |
else | |
{ | |
Write-Host ("Transfer of {0} failed: {1}" -f $e.FileName, $e.Error) | |
} | |
} | |
Function Format-FileSize() { | |
Param ([int]$size) | |
If ($size -gt 1TB) {[string]::Format("{0:0.00} TB", $size / 1TB)} | |
ElseIf ($size -gt 1GB) {[string]::Format("{0:0.00} GB", $size / 1GB)} | |
ElseIf ($size -gt 1MB) {[string]::Format("{0:0.00} MB", $size / 1MB)} | |
ElseIf ($size -gt 1KB) {[string]::Format("{0:0.00} kB", $size / 1KB)} | |
ElseIf ($size -gt 0) {[string]::Format("{0:0} B", $size)} | |
Else {""} | |
} | |
$assemblyPath = "c:\Program Files (x86)\WinSCP" | |
$dllPath = (Join-Path $assemblyPath "WinSCPnet.dll") | |
# Load WinSCP .NET assembly | |
Add-Type -Path $dllPath | |
# Setup session options | |
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{ | |
Protocol = [WinSCP.Protocol]::Ftp | |
HostName = $sessionUrl | |
UserName = $username | |
Password = $password | |
} | |
$started = Get-Date | |
#$session = New-Object WinSCP.Session | |
#$session.Open($sessionOptions) | |
#$result = $session.RemoveFiles($remotePath) | |
#$session.Close() | |
#Write-Host ("Files deleted: $result") | |
try | |
{ | |
Write-Host ("Retrieving files...") | |
# Retrieve list of files and sort them from larges to smallest | |
$files = Get-ChildItem -Path $localPath -Recurse –File | |
# Calculate total size of all files | |
$total = Format-FileSize(($files | Measure-Object -Property Length -Sum).Sum) | |
Write-Host ("Preparing {0} file(s) with total size of {1}..." -f $files.Length, $total) | |
# Start the background job for the batch | |
$result = $files | Split-Pipeline -Verbose -Count $batches -Function FileTransferred, Format-FileSize -Variable dllPath, sessionOptions, remotePath, localPath { $files = @($input) | |
# Load WinSCP .NET assembly. | |
# Need to use an absolute path as the Job is started from user's documents folder. | |
Add-Type -Path $dllPath | |
$size = $files.Count | |
$total = ( $files | Measure-Object -Property Length -Sum).Sum | |
$totalF = Format-FileSize($total) | |
Write-Host ("Connecting host for uploading {0} file(s) with total size of {1}..." -f $size, $totalF) | |
$session = New-Object WinSCP.Session | |
# Subscribe to the event | |
#$session.add_FileTransferred( { FileTransferred($_) } ) | |
$session.Open($sessionOptions) | |
# Upload the files selected for this batch | |
foreach ($file in $files) | |
{ | |
$localFilePath = $file.FullName | |
$remoteFilePath = $session.TranslateLocalPathToRemote($file.FullName, $localPath, $remotePath); | |
$subtotal = $subtotal + $file.Length | |
$progress = [Math]::Round($subtotal * 100 / $total, 2) | |
$size = Format-FileSize($file.Length) | |
Write-Host ("Upload $remoteFilePath ({0})" -f $size) | |
[timespan]$time = (Measure-Command { | |
$session.PutFiles($file.FullName, $session.EscapeFileMask($remoteFilePath)).Check() | |
}).Duration() | |
$rate = Format-FileSize($file.Length / $time.TotalSeconds) | |
Write-Host ("Complete $remoteFilePath ({1}/s, {2}) - {0}% of batch" -f $progress, $rate, $time) | |
} | |
# Disconnect, clean up | |
Write-Host ("Disconnecting host {0}..." -f $no) | |
Write-Host $result | |
$session.Dispose() | |
} | |
Write-Host "All files uploaded." | |
$ended = Get-Date | |
Write-Host ("Took {0}" -f (New-TimeSpan -Start $started -End $ended)) | |
} | |
finally | |
{ | |
# Disconnect, clean up | |
} | |
exit 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Module for Parallel Data Processing in PowerShell | |
# https://github.com/nightroman/SplitPipeline | |
Install-Package SplitPipeline -ProviderName NuGet -Force | |
Install-Module SplitPipeline -Force | |
# Install WinSCP with .NET Assembly | |
choco install winscp -y | |
$env:Path += ";c:\Program Files (x86)\WinSCP" | |
# Execute deploy script | |
powershell -file deploy.ps1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment