powershell 和 FTP,脚本不等待传输完成

powershell and FTP, script not waiting for transfer to complete

我有一个脚本,简而言之,它执行以下操作:

  1. 将所需文件复制到临时文件夹
  2. 将临时文件夹中的文件压缩为 .zip 文件
  3. FTP将 .zip 文件发送到我们的 FTP 服务器
  4. 整理并删除临时文件夹和 .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 秒超时时有效。

非常感谢您的帖子和帮助。