问题描述
我正在编写一个监视目录的 Powershell 脚本,当一个文件(或多个)上传到目录中时,它会获取这些文件,将它们复制到另一个文件夹,将它们发送到 FTP 服务器,然后删除来自原始目录的文件。
我在连接到 FTP 服务器时遇到问题。我不确定问题是否出在我配置 Web 客户端的方式上,或者问题出在 ftp URI 中有空格而我没有正确转义它们。
代码如下:
$source = "c:/testFtp"
$ftpdestination = "ftp://username:password@ftp.ftpsite.com/folder with space/folder with space"
$webclient = New-Object -TypeName System.Net.WebClient
$files = Get-ChildItem $source
foreach ($file in $files)
{
Write-Host "Uploading $file"
try {
$ftp = "$ftpdestination/$file"
$uri = New-Object -TypeName System.Uri -ArgumentList $ftp
$webclient.UploadFile($uri,$source/$file)
} catch {
Add-content "$logs" -value "There was an error uploading to ftp"
}
}
$webclient.dispose()
我曾尝试以多种方式转义文件夹空间,所以我开始认为这不是问题,而且我没有正确配置 Web 客户端。
它也不会经常捕获错误,所以我不相信当 web 客户端上传失败时它会抛出错误。任何帮助表示赞赏!
解决方法
答案:
事实证明 WebClient 连接正确,但 SSL 阻止发送文件。我通过使用 C# 编译和运行脚本发现了这一点,它为我提供了更好的错误处理,因为我是 Powershell 脚本的新手,似乎无法获得良好的错误处理。
经过研究,我找不到通过 WebClient 启用 SSL 的方法,因此我切换到 FtpWebRequest。这是成功的代码(这个 try catch 块似乎没有像我想要的那样记录错误,但该工具现在可以成功地将文件发送到 ftp 服务器:
try {
$ftp = [System.Net.FtpWebRequest]::Create("$ftpsite/$filename")
$ftp = [System.Net.FtpWebRequest]$ftp
$ftp.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile
$ftp.Credentials = new-object System.Net.NetworkCredential("$username","$password")
$ftp.UseBinary = $true
$ftp.UsePassive = $true
$ftp.EnableSSL = $true #<-----------------This was the line that made this work
$ftp.KeepAlive = $false
# read in the file to upload as a byte array
$content = [System.IO.File]::ReadAllBytes("$source/$file")
$ftp.ContentLength = $content.Length
# get the request stream,and write the bytes into it
$rs = $ftp.GetRequestStream()
$rs.Write($content,$content.Length)
# be sure to clean up after ourselves
$rs.Close()
$rs.Dispose()
Write-Host "Successfully uploaded: $source/$file"
Copy-Item "$source/$file" -Destination "$copydestination"
Remove-Item "$source/$file"
$logline = "$(Get-Date),Added File: $file to $copydestination"
Add-content "$logs" -value $logline
} catch {
$res = $ftp.GetResponse()
Add-content "$logs" -value "There was an error: $res.StatusCode"
Write-Error -Message "There was an error." -ErrorAction Stop
}