Design Scope: Use PowerShell and WinSCP .NET assembly to automate nightly downloads by using the file timestamp to identify the files to be downloaded. The FTP server being connected to is IIS so it does not support all commands like MLSD in it's current configuration and I don't see them making a change if requested.
Problem: Files that have a 1 or 2 digit month return different string lengths that I'm unsure how to get around this. My code works now, but will stop working in October.
e.g. March displays 3/dd/yyyy instead of 03/dd/yyyy
Other notes: At first I tried scripting this using WinSCP.com, but I could not find a way to specify the date correctly.
e.g. you can specify *.zip>=1D
or *.zip<=1D
, but *.zip=1D
or *.zip==1D
are not currently supported with the latest release of WinSCP.
Code:
$yesterday = [DateTime]::Today.AddDays(-1).ToString("M/dd/yyyy")# OR I have to use ToString("MM/dd/yyyy") for months 10-12,# but I need both formats to work.#delete the temporary filedel .\FTPfiles.txt# Load WinSCP .NET assemblyAdd-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"# Setup session options$sessionOptions = New-Object WinSCP.SessionOptions -Property @{ Protocol = [WinSCP.Protocol]::Ftp HostName = "server.com" UserName = "joe" Password = "smith"}$session = New-Object WinSCP.Session try { # Connect $session.Open($sessionOptions) $directory = $session.ListDirectory("/Folder") foreach ($fileInfo in $directory.Files) { Write-Output ("{1} {0}" -f $fileInfo.Name, $fileInfo.LastWriteTime) >> FTPfiles.txt } $fileList = get-content .\FTPfiles.txt | findstr $yesterday $stripped = $fileList -creplace '^.*Z12', 'Z12' # Download files $remotePath = "/Folder/" $transferOptions = New-Object WinSCP.TransferOptions $transferOptions.TransferMode = [WinSCP.TransferMode]::Binary $lines = $stripped foreach ($line in $lines) { Write-Host ("Downloading {0} ..." -f $line) $session.GetFiles($remotePath+$line, "C:\Downloads\").Check() } }catch [Exception]{ Write-Host ("Error: {0}" -f $_.Exception.Message) exit 1}finally{ # Disconnect, clean up $session.Dispose()}
The $fileInfo in $directory.Files
writes the last write time and then file name into FTPfiles.txt
for all of the files contained on the FTP server from the specified folder. This text file is then read and then further reduced to just the files that have a write time that occurred on yesterday's date, which currently only works 9 months out of the year because of the date format using 1 digit for the month instead of 2 digits.
Next that file is read and stripped of the dates before the filenames so that the filenames will be used to loop through to download. The transformation looks like this:
FROM:3/14/2017 2:04:00 AM Z1234_20170314050001_1.zip3/14/2017 3:04:00 AM Z1234_20170315060002_1.zip3/14/2017 4:04:00 AM Z1234_20170316070001_1.zip3/14/2017 5:04:00 AM Z1234_20170317080001_1.zipTO:Z1234_20170314050001_1.zipZ1234_20170315060002_1.zipZ1234_20170316070001_1.zipZ1234_20170317080001_1.zip
Then the script uses those filenames to download the needed files from the previous day.