powershell 和 FTP,脚本不等待传输完成
powershell and FTP, script not waiting for transfer to complete
我有一个脚本,简而言之,它执行以下操作:
- 将所需文件复制到临时文件夹
- 将临时文件夹中的文件压缩为 .zip 文件
- FTP将 .zip 文件发送到我们的 FTP 服务器
- 整理并删除临时文件夹和 .zip 文件
我从之前的 post 中提取了 FTP 代码:
Upload files with FTP using PowerShell
并在必要时修改它(保持基础知识 - 我认为)。
我遇到的问题是,当 .zip 文件正在 FTP 时,脚本不会等到它完成。在它继续执行之前,它会从 20Mb 到 60Mb 的任何地方完成,整理并删除它正在传输的文件。
临时文件夹始终相同,但 .zip 文件名因日期而异,因此我无法真正颠倒操作顺序。
任何人都可以建议我如何让脚本等待 FTP 进程完成,无论是成功还是失败,然后再继续?
干杯,
安德鲁.
编辑:对于那些提出问题的人......
function FTPtoServer ()
{
<#
What this function has to/should do:
- accept the right number of parameters,
minimum/mandatory: username, password, file
optional: proxy server address/port, proxy username and password
- check that the source file exists, then extract the filename.
- if a proxy is specified, set the appropriate parameters
- transmit the file
- if any errors occur, throw and return
#>
param(
[string]$sourcefile=$(throw 'A sourcefile is required, -sourcefile'), <#fully qualified zip file name#>
[string]$FTPUser =$(throw 'An FTP username is required, -ftpuser'),
[string]$FTPPass =$(throw 'An FTP password is required, -ftppass'),
#
[string]$proxyServer, #proxySocket?? it is an address and port
[string]$proxyUser,
[string]$proxyPass
)
#local variables
$FTPserver = "ftp://ftp.servername.com.au"
#check if the sourcefile exists, if not return/throw an error
# The sourcefile should contain the full path to the file.
if (-not (test-path $sourcefile)){
throw "the source file could not be located: $sourcefile"
}
# extract the filename from the sourcefile.
$filename = split-path -path $sourcefile -leaf
# create the FtpWebRequest and configure it
$ftp = [System.Net.FtpWebRequest]::Create("$FTPserver/$filename")
$ftp = [System.Net.FtpWebRequest]$ftp
$ftp.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile
$ftp.Credentials = new-object System.Net.NetworkCredential($FTPUser,$FTPPass)
$ftp.UseBinary = $true
$ftp.UsePassive = $false
#proxy info
# ******** DANGER Will Robinson - this proxy config has not been
# tested and may not work.
if ($proxyServer){
$proxy = New-Object System.Net.WebProxy $proxyServer
if ($proxyUser -and $proxyPass){
$proxy.Credentials = new-object System.Net.NetworkCredential($proxyUser,$proxyPass)
}
$ftp.Proxy = $proxy
$ftp.UsePassive = $true #apparently, must usePassive if using proxy
}
#now we have checked and prepared everything, lets try and send the file.
# read in the file to upload as a byte array
try{
#work out how much we are sending
$content = [System.IO.File]::ReadAllBytes("$sourceFile")
$ftp.ContentLength = $content.Length
try {
# get the request stream, and write the bytes into it
$rs = $ftp.GetRequestStream()
$rs.Write($content, 0, $content.Length)
# be sure to clean up after ourselves
$rs.Close()
$rs.Dispose()
}
catch {
$errorMessage = "FTP failed. " + $_.exception.message
throw $errormessage
}
}
catch {
$errorMessage = "Unable to transmit file " + $sourceFile + "`r`n" + $_.exception.message
throw $errormessage
}
}
以上内容在一个单独的文件中,但被以下内容调用:
try {
FTPtoServer -sourcefile $sourcefile -ftpuser $FTPUser -ftppass $FTPPass
}
catch {
$errorMessage = "FTPtoServer function failed with error: $_"
finishFail -failmessage $errorMessage
}
干杯。
我自己使用了另一种老派方法,它应该适合你,并且不需要服务器上的任何额外组件。
$ftp_user = "username"
$ftp_password = "password"
$ftp_address = "ftp.someserver.com"
$ftp_commands = @"
open $ftp_address
$ftp_user
$ftp_password
lcd c:\jobs\output
put estate_data_current.xml
bye
"@
set-content -encoding "ASCII" -path ftp_commands.txt -value $ftp_commands
ftp -s:ftp_commands.txt
找到了。
我使用一个大文件 (~140Mb) 单独执行上面的 FTP 代码,它抛出了错误; "The underlying connection was closed: An unexpected error occured on a receive."
我重新启动了 FTP 服务器,检查了用户帐户等
我也用同样的文件测试了 M$ FTP 客户端,它完全正确地传输了。
无论如何,我找到了这篇文章:https://www.codeproject.com/Questions/597175/FileplusUploadplustoplusFTPplusserver,其中也有我收到的错误。
事实证明,FTPWebRequest 的超时值不是 doco 中的 -1,而是 100 秒。
我检查了我的 FTP 日志,果然,登录和注销之间的时间大约为 100 秒。
我在我的代码中添加了行:$ftp.Timeout = -1 并且第一次尝试完全无误地传输整个文件。
之前的传输在低于 100 秒超时时有效。
非常感谢您的帖子和帮助。
我有一个脚本,简而言之,它执行以下操作:
- 将所需文件复制到临时文件夹
- 将临时文件夹中的文件压缩为 .zip 文件
- FTP将 .zip 文件发送到我们的 FTP 服务器
- 整理并删除临时文件夹和 .zip 文件
我从之前的 post 中提取了 FTP 代码: Upload files with FTP using PowerShell 并在必要时修改它(保持基础知识 - 我认为)。
我遇到的问题是,当 .zip 文件正在 FTP 时,脚本不会等到它完成。在它继续执行之前,它会从 20Mb 到 60Mb 的任何地方完成,整理并删除它正在传输的文件。
临时文件夹始终相同,但 .zip 文件名因日期而异,因此我无法真正颠倒操作顺序。
任何人都可以建议我如何让脚本等待 FTP 进程完成,无论是成功还是失败,然后再继续?
干杯,
安德鲁.
编辑:对于那些提出问题的人......
function FTPtoServer ()
{
<#
What this function has to/should do:
- accept the right number of parameters,
minimum/mandatory: username, password, file
optional: proxy server address/port, proxy username and password
- check that the source file exists, then extract the filename.
- if a proxy is specified, set the appropriate parameters
- transmit the file
- if any errors occur, throw and return
#>
param(
[string]$sourcefile=$(throw 'A sourcefile is required, -sourcefile'), <#fully qualified zip file name#>
[string]$FTPUser =$(throw 'An FTP username is required, -ftpuser'),
[string]$FTPPass =$(throw 'An FTP password is required, -ftppass'),
#
[string]$proxyServer, #proxySocket?? it is an address and port
[string]$proxyUser,
[string]$proxyPass
)
#local variables
$FTPserver = "ftp://ftp.servername.com.au"
#check if the sourcefile exists, if not return/throw an error
# The sourcefile should contain the full path to the file.
if (-not (test-path $sourcefile)){
throw "the source file could not be located: $sourcefile"
}
# extract the filename from the sourcefile.
$filename = split-path -path $sourcefile -leaf
# create the FtpWebRequest and configure it
$ftp = [System.Net.FtpWebRequest]::Create("$FTPserver/$filename")
$ftp = [System.Net.FtpWebRequest]$ftp
$ftp.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile
$ftp.Credentials = new-object System.Net.NetworkCredential($FTPUser,$FTPPass)
$ftp.UseBinary = $true
$ftp.UsePassive = $false
#proxy info
# ******** DANGER Will Robinson - this proxy config has not been
# tested and may not work.
if ($proxyServer){
$proxy = New-Object System.Net.WebProxy $proxyServer
if ($proxyUser -and $proxyPass){
$proxy.Credentials = new-object System.Net.NetworkCredential($proxyUser,$proxyPass)
}
$ftp.Proxy = $proxy
$ftp.UsePassive = $true #apparently, must usePassive if using proxy
}
#now we have checked and prepared everything, lets try and send the file.
# read in the file to upload as a byte array
try{
#work out how much we are sending
$content = [System.IO.File]::ReadAllBytes("$sourceFile")
$ftp.ContentLength = $content.Length
try {
# get the request stream, and write the bytes into it
$rs = $ftp.GetRequestStream()
$rs.Write($content, 0, $content.Length)
# be sure to clean up after ourselves
$rs.Close()
$rs.Dispose()
}
catch {
$errorMessage = "FTP failed. " + $_.exception.message
throw $errormessage
}
}
catch {
$errorMessage = "Unable to transmit file " + $sourceFile + "`r`n" + $_.exception.message
throw $errormessage
}
}
以上内容在一个单独的文件中,但被以下内容调用:
try {
FTPtoServer -sourcefile $sourcefile -ftpuser $FTPUser -ftppass $FTPPass
}
catch {
$errorMessage = "FTPtoServer function failed with error: $_"
finishFail -failmessage $errorMessage
}
干杯。
我自己使用了另一种老派方法,它应该适合你,并且不需要服务器上的任何额外组件。
$ftp_user = "username"
$ftp_password = "password"
$ftp_address = "ftp.someserver.com"
$ftp_commands = @"
open $ftp_address
$ftp_user
$ftp_password
lcd c:\jobs\output
put estate_data_current.xml
bye
"@
set-content -encoding "ASCII" -path ftp_commands.txt -value $ftp_commands
ftp -s:ftp_commands.txt
找到了。
我使用一个大文件 (~140Mb) 单独执行上面的 FTP 代码,它抛出了错误; "The underlying connection was closed: An unexpected error occured on a receive."
我重新启动了 FTP 服务器,检查了用户帐户等
我也用同样的文件测试了 M$ FTP 客户端,它完全正确地传输了。
无论如何,我找到了这篇文章:https://www.codeproject.com/Questions/597175/FileplusUploadplustoplusFTPplusserver,其中也有我收到的错误。
事实证明,FTPWebRequest 的超时值不是 doco 中的 -1,而是 100 秒。
我检查了我的 FTP 日志,果然,登录和注销之间的时间大约为 100 秒。
我在我的代码中添加了行:$ftp.Timeout = -1 并且第一次尝试完全无误地传输整个文件。
之前的传输在低于 100 秒超时时有效。
非常感谢您的帖子和帮助。