Modyfikacja wtyczki WinSCP
Dodałem funkcję której mi brakowało
- Case
- Zmiany
- Kod wtyczki
- @name &Keep Local Directory up to Date and Delete Remote…
- @command powershell.exe -ExecutionPolicy Bypass -File “%EXTENSION_PATH%” ^
- -sessionUrl “!E” -localPath “%LocalPath%” -remotePath “%RemotePath%” ^
- %Delete% %DeleteRemote% %Beep% %ContinueOnError% -interval “%Interval%” ^
- -fileMask “%FileMask%” -pause -sessionLogPath “%SessionLogPath%” -minDownloadAge “%MinDownloadAge%”
- @description Periodically scans for changes in a remote directory, ^
- reflects them on a local directory and optionally deletes remote files
- @version 14
- @homepage https://winscp.net/eng/docs/library_example_keep_local_directory_up_to_date
- @require WinSCP 5.16
- @option - -run group “Directories”
- @option RemotePath -run textbox “&Watch for changes in the remote directory:” “!/”
- @option LocalPath -run textbox ^
- “… &and automatically reflect them on the local directory:” “!\”
- @option - -config -run group “Options”
- @option Delete -config -run checkbox “&Delete local files” “” -delete
- @option DeleteRemote -config -run checkbox “Delete &remote files after download” “” -deleteRemote
- @option Beep -config -run checkbox “&Beep on change” “” -beep
- @option ContinueOnError -config -run checkbox “Continue on &error” “” -continueOnError
- @option Interval -config -run textbox “&Interval (in seconds):” “30”
- @option FileMask -config -run textbox “File &mask:” “”
- @option MinDownloadAge -config -run textbox “Minimum download age (in seconds):” “5”
- @option - -config group “Logging”
- @option SessionLogPath -config sessionlogfile
- Pause if -pause switch was used
- Never exits cleanly
Case
Używam WinSCP do synchronizacji zdalnego katalogu FTP z lokalnym folderem. Pliki są automatycznie pobierane z katalogu i wczytywane do Lightrooma. Na serwer FTP pliki są wgrywane bezpośrednio z apartu podłączonego do sieci.
+---------+ FTP Upload +------------+
| Camera | ----------------------> | FTP Server |
+---------+ (smartphone hotspot) +------------+
|
| Sync via
| WinSCP
v
+--------------+
| Computer |
| (Local Dir) |
+--------------+
|
| Auto-import
v
+------------------+
| Adobe Lightroom |
+------------------+
Zmiany
- Dodałem opcję pobierania tylko plików króych czas modyfikacji jest starszy niż określona ilość sekund. Rozwiązuje to prawie całkowicie problem pobierania niekompletnych plików które są właśnie wgrywane na serwer.
- Dodałem funkcję do automatycznego usuwania plików z serwera po ich pobraniu.
Kod wtyczki
Lokalizacja pliku wtyczki: ~\WinSCP\Extensions\KeepLocalUpToDate.WinSCPextension.ps1
~~~powershell
@name &Keep Local Directory up to Date and Delete Remote…
@command powershell.exe -ExecutionPolicy Bypass -File “%EXTENSION_PATH%” ^
-sessionUrl “!E” -localPath “%LocalPath%” -remotePath “%RemotePath%” ^
%Delete% %DeleteRemote% %Beep% %ContinueOnError% -interval “%Interval%” ^
-fileMask “%FileMask%” -pause -sessionLogPath “%SessionLogPath%” -minDownloadAge “%MinDownloadAge%”
@description Periodically scans for changes in a remote directory, ^
reflects them on a local directory and optionally deletes remote files
@version 14
@homepage https://winscp.net/eng/docs/library_example_keep_local_directory_up_to_date
@require WinSCP 5.16
@option - -run group “Directories”
@option RemotePath -run textbox “&Watch for changes in the remote directory:” “!/”
@option LocalPath -run textbox ^
“… &and automatically reflect them on the local directory:” “!\”
@option - -config -run group “Options”
@option Delete -config -run checkbox “&Delete local files” “” -delete
@option DeleteRemote -config -run checkbox “Delete &remote files after download” “” -deleteRemote
@option Beep -config -run checkbox “&Beep on change” “” -beep
@option ContinueOnError -config -run checkbox “Continue on &error” “” -continueOnError
@option Interval -config -run textbox “&Interval (in seconds):” “30”
@option FileMask -config -run textbox “File &mask:” “”
@option MinDownloadAge -config -run textbox “Minimum download age (in seconds):” “5”
@option - -config group “Logging”
@option SessionLogPath -config sessionlogfile
param ( $sessionUrl = “sftp://user:mypassword;fingerprint=ssh-rsa-xxxxxxxxxxx…@example.com/”, [Parameter(Mandatory = $True)] $localPath, [Parameter(Mandatory = $True)] $remotePath, [Switch] $delete, [Switch] $deleteRemote, [Switch] $beep, [Switch] $continueOnError, $sessionLogPath = $Null, $interval = 30, $fileMask = $Null, [Switch] $pause, $minDownloadAge = 5 )
function Beep() { if ($beep) { [System.Console]::Beep() } }
function HandleException ($e) { if ($continueOnError) { Write-Host -ForegroundColor Red $_.Exception.Message Beep } else { throw $e } }
function SetConsoleTitle ($status) { if ($sessionOptions) { $status = “$sessionOptions - $status” } $Host.UI.RawUI.WindowTitle = $status }
try { # Load WinSCP .NET assembly $assemblyPath = if ($env:WINSCP_PATH) { $env:WINSCP_PATH } else { $PSScriptRoot } Add-Type -Path (Join-Path $assemblyPath “WinSCPnet.dll”)
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.ParseUrl($sessionUrl)
$transferOptions = New-Object WinSCP.TransferOptions -Property @{ FileMask = $fileMask };
$session = New-Object WinSCP.Session
try {
$session.SessionLogPath = $sessionLogPath
Write-Host "Connecting..."
SetConsoleTitle "Connecting"
$session.Open($sessionOptions)
while ($True) {
Write-Host -NoNewline "Looking for changes..."
SetConsoleTitle "Looking for changes"
try {
# Track successfully downloaded files
$downloadedFiles = @()
$differences =
$session.CompareDirectories(
[WinSCP.SynchronizationMode]::Local, $localPath, $remotePath, $delete,
$False, [WinSCP.SynchronizationCriteria]::Time, $transferOptions)
Write-Host
if ($differences.Count -eq 0) {
Write-Host "No changes found."
}
else {
Write-Host "Synchronizing $($differences.Count) change(s)..."
SetConsoleTitle "Synchronizing changes"
foreach ($difference in $differences) {
$action = $difference.Action
if ($action -eq [WinSCP.SynchronizationAction]::DownloadNew) {
$message = "Downloading new $($difference.Remote.FileName)..."
}
elseif ($action -eq [WinSCP.SynchronizationAction]::DownloadUpdate) {
$message = "Downloading updated $($difference.Remote.FileName)..."
}
elseif ($action -eq [WinSCP.SynchronizationAction]::DeleteLocal) {
$message = "Deleting local $($difference.Local.FileName)..."
}
else {
throw "Unexpected difference $action"
}
Write-Host -NoNewline $message
try {
# Check if the file's last modification date is older than the specified minimum age
$lastWriteTime = $difference.Remote.LastWriteTime
$currentTime = [System.DateTime]::Now
$timeDifference = $currentTime - $lastWriteTime
if ($timeDifference.TotalSeconds -gt $minDownloadAge) {
$difference.Resolve($session, $transferOptions) | Out-Null
Write-Host " Done."
Beep
# Track successfully downloaded files
if (($action -eq [WinSCP.SynchronizationAction]::DownloadNew) -or
($action -eq [WinSCP.SynchronizationAction]::DownloadUpdate)) {
$downloadedFiles += $difference.Remote
}
} else {
Write-Host " Skipping download of $($difference.Remote.FileName) as it was modified less than $minDownloadAge seconds ago."
}
}
catch {
Write-Host
HandleException $_
}
}
# Delete only the files that were successfully downloaded
if ($deleteRemote -and $downloadedFiles.Count -gt 0) {
Write-Host "Deleting successfully downloaded remote files..."
foreach ($remoteFile in $downloadedFiles) {
try {
# Konstrukcja poprawnej ścieżki
$remoteFilePath = [System.IO.Path]::Combine($remotePath.TrimEnd('/'), $remoteFile.FileName).Replace('\\', '/')
Write-Host "Attempting to delete: $remoteFilePath"
$result = $session.RemoveFiles($remoteFilePath)
if ($result.IsSuccess) {
Write-Host "Deleted: $($remoteFile.FileName)"
} else {
Write-Host "Failed to delete: $($remoteFile.FileName)"
Write-Host -ForegroundColor Red $result.Failures[0].Message
}
}
catch {
Write-Host
HandleException $_
}
}
}
}
}
catch {
Write-Host
HandleException $_
}
SetConsoleTitle "Waiting"
$wait = [int]$interval
# Wait for 1 second in a loop, to make the waiting breakable
while ($wait -gt 0) {
Write-Host -NoNewLine "\`rWaiting for $wait seconds, press Ctrl+C to abort... "
Start-Sleep -Seconds 1
$wait--
}
Write-Host
Write-Host
}
}
finally {
Write-Host # to break after "Waiting..." status
Write-Host "Disconnecting..."
# Disconnect, clean up
$session.Dispose()
} } catch {
$continueOnError = $True
HandleException $_
SetConsoleTitle "Error" }
Pause if -pause switch was used
if ($pause) { Write-Host “Press any key to exit…” [System.Console]::ReadKey() | Out-Null }
Never exits cleanly
exit 1 ~~~