# Sync-only upload: upload files that are missing or size-mismatched on FTP $ErrorActionPreference = "Continue" $FtpHost="116.198.221.125"; $FtpPort=21; $FtpUser="wenchuanyi"; $FtpPass="r7P^f*v7rFts" $RemoteRoot="/wwwroot" $Stage = Join-Path $env:TEMP "wcy_publish_staging" $Log = "D:\CodeBuddy\Pros\WenChuanyi\deploy\ftp_sync.log" $fail = $false Set-Content -Path $Log -Value "=== sync start $(Get-Date -Format 'HH:mm:ss') ===" -Encoding UTF8 function L([string]$m){ Add-Content -Path $Log -Value $m -Encoding UTF8 } function New-FtpReq([string]$path,[string]$method,[int]$timeoutMs=90000){ $uri="ftp://${FtpHost}:${FtpPort}/"+$path.TrimStart('/') $r=[System.Net.FtpWebRequest]::Create($uri) $r.Method=$method $r.Credentials=New-Object System.Net.NetworkCredential($FtpUser,$FtpPass) $r.UsePassive=$true; $r.UseBinary=$true; $r.KeepAlive=$false $r.Timeout=$timeoutMs return $r } function Get-FtpSize([string]$p){ for($i=0;$i -lt 3;$i++){ try{ $r=New-FtpReq $p ([System.Net.WebRequestMethods+Ftp]::GetFileSize) 30000 $resp=$r.GetResponse(); $s=$resp.ContentLength; $resp.Close() return $s }catch{ Start-Sleep -Seconds 2 } } return -1 } function UpFile([string]$lp,[string]$rp){ $localSize=(Get-Item $lp).Length $remoteSize=Get-FtpSize $rp if($remoteSize -eq $localSize){ L "SKIP $rp"; return } L "UPLOAD $rp (remote=$remoteSize local=$localSize)" for($i=1;$i -le 3;$i++){ try{ $r=New-FtpReq $rp ([System.Net.WebRequestMethods+Ftp]::UploadFile) 180000 $b=[System.IO.File]::ReadAllBytes($lp) $r.ContentLength=$b.Length $s=$r.GetRequestStream() try{ $s.Write($b,0,$b.Length) } finally { $s.Close() } $resp=$r.GetResponse(); try{ $resp.Close() }catch{} Start-Sleep -Seconds 1 $after=Get-FtpSize $rp if($after -eq $localSize){ L "OK $rp"; return } L "VERIFYFAIL $rp (got $after)"; continue }catch{ L "RETRY($i) $rp : $($_.Exception.Message)" Start-Sleep -Seconds 5 } } L "FAIL $rp" $script:fail=$true } function UpDir([string]$ld,[string]$rd){ foreach($d in Get-ChildItem $ld -Directory){ $c="$rd/$($d.Name)" $mr=New-FtpReq $c ([System.Net.WebRequestMethods+Ftp]::MakeDirectory) 30000 try{ $null=$mr.GetResponse() }catch{} UpDir $d.FullName $c } foreach($f in Get-ChildItem $ld -File){ UpFile $f.FullName "$rd/$($f.Name)" } } if(-not (Test-Path $Stage)){ L "STAGING_MISSING"; exit 1 } UpDir $Stage $RemoteRoot if($fail){ L "RESULT=PARTIAL_FAIL" } else { L "RESULT=OK" } L "=== sync end $(Get-Date -Format 'HH:mm:ss') ==="