param (
[string]$ftpHost = “your_ftp_host”,
[string]$ftpUser = “your_ftp_username”,
[string]$ftpPass = “your_ftp_password”,
[string]$remoteDir = “/remote/directory/path”,
[string]$localDir = “C:/local/directory/path”
)
function Get-FtpRequest {
param (
[string]$uri,
[string]$method = “GET”
)
$request = [System.Net.FtpWebRequest]::Create($uri)
$request.Method = $method
$request.Credentials = New-Object System.Net.NetworkCredential($ftpUser, $ftpPass)
$request.UsePassive = $true
return $request
}
function Upload-File {
param (
[string]$localFile,
[string]$remoteFile
)
Write-Host “Uploading $localFile to $remoteFile”
$uri = “ftp://$ftpHost$remoteFile”
$request = Get-FtpRequest -uri $uri -method “STOR”
$request.UseBinary = $true
$request.UsePassive = $true
$request.KeepAlive = $false
$fileStream = [System.IO.File]::OpenRead($localFile)
$requestStream = $request.GetRequestStream()
$fileStream.CopyTo($requestStream)
$fileStream.Close()
$requestStream.Close()
}
function Get-Remote-Timestamp {
param (
[string]$remoteFile
)
$uri = “ftp://$ftpHost$remoteFile”
$request = Get-FtpRequest -uri $uri -method “MDTM”
try {
$response = $request.GetResponse()
$reader = New-Object IO.StreamReader $response.GetResponseStream()
$timestamp = $reader.ReadToEnd().Substring(4)
$reader.Close()
$response.Close()
return [datetime]::ParseExact($timestamp, “yyyyMMddHHmmss”, $null)
}
catch {
return $null
}
}
function Create-Remote-Directory {
param (
[string]$remoteDir
)
$uri = “ftp://$ftpHost$remoteDir”
$request = Get-FtpRequest -uri $uri -method “MKD”
try {
$request.GetResponse() | Out-Null
}
catch [System.Net.WebException] {
# Ignore errors for directory already existing
}
}
function Sync-Directory {
param (
[string]$localPath,
[string]$remotePath
)
if (-not (Test-Path $localPath)) {
Write-Error “Local path does not exist: $localPath”
return
}
if ($remotePath -eq “”) {
$remotePath = “/”
}
$localFiles = Get-ChildItem -Path $localPath -Recurse
foreach ($localFile in $localFiles) {
if ($localFile.PSIsContainer) {
$relativePath = $localFile.FullName.Substring($localDir.Length)
$relativePath = $relativePath -replace “\\”, “/”
$remoteDirPath = “$remotePath/$relativePath”
Create-Remote-Directory -remoteDir $remoteDirPath
}
else {
$relativePath = $localFile.FullName.Substring($localDir.Length)
$relativePath = $relativePath -replace “\\”, “/”
$remoteFile = “$remotePath/$relativePath”
$remoteDirPath = [System.IO.Path]::GetDirectoryName($remoteFile).Replace(“\”, “/”)
Create-Remote-Directory -remoteDir $remoteDirPath
# Get remote file timestamp
$remoteTimestamp = Get-Remote-Timestamp -remoteFile $remoteFile
# Compare timestamps
if ($remoteTimestamp -eq $null -or $localFile.LastWriteTime -gt $remoteTimestamp) {
Upload-File -localFile $localFile.FullName -remoteFile $remoteFile
}
}
}
}
Sync-Directory -localPath $localDir -remotePath $remoteDir