【问题标题】:How do I query a file on FTP server in PowerShell to determine if an upload is required?如何在 PowerShell 中查询 FTP 服务器上的文件以确定是否需要上传?
【发布时间】:2017-10-19 20:22:23
【问题描述】:

该项目是一个使用 VS2017 和(本地)TFS2017 编码和构建的 MVC 网站。构建定义当前正在工作并在签入时发布到暂存位置。

下面的 PowerShell 脚本源自 David Kittle's website,正在使用,但它每次都会上传所有文件。我使用 cmets 对清单进行了缩写,以专注于我想寻求帮助/指导的脚本部分。

# Setup the FTP connection, destination URL and local source directory
# Put the folders and files to upload into $Srcfolders and $SrcFiles
# Create destination folders as required

# start file uploads
foreach($entry in $SrcFiles)
{
    #Create full destination filename from $entry and put it into $DesFile
    $uri = New-Object System.Uri($DesFile) 

    #NEED TO GET THE REMOTE FILE DATA HERE TO TEST AGAINST THE LOCAL FILE
    If (#perform a test to see if the file needs to be uploaded)
        { $webclient.UploadFile($uri, $SrcFullname) }
}

在上面脚本的最后几行中,我需要确定源文件是否需要上传。我假设我可以检查时间戳来确定这一点。所以;

如果我的假设是错误的,请告知检查所需上传的最佳方法。

如果我的假设是正确的,我如何 (1) 从远程服务器检索时间戳,然后 (2) 对本地文件进行检查?

【问题讨论】:

    标签: powershell ftp webclient continuous-delivery


    【解决方案1】:

    您可以使用FtpWebRequest class 及其GetDateTimestamp FTP "method" 并解析它返回的UTC 时间戳字符串。格式由RFC 3659 指定为YYYYMMDDHHMMSS[.sss]

    只有当 FTP 服务器支持该方法在后台使用的MDTM 命令时才有效(大多数服务器支持,但不是全部)。

    $url = "ftp://ftp.example.com/remote/folder/file.txt"
    $ftprequest = [System.Net.FtpWebRequest]::Create($url)
    
    $ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::GetDateTimestamp
    
    $response = $ftprequest.GetResponse().StatusDescription
    
    $tokens = $response.Split(" ")
    
    $code = $tokens[0]
    
    if ($code -eq 213)
    {
        Write-Host "Timestamp is $($tokens[1])"
    }
    else
    {
        Write-Host "Error $response"
    }
    

    它会输出如下内容:

    Timestamp is 20171019230712
    

    现在您解析它,并与本地文件的 UTC 时间戳进行比较:

    (Get-Item "file.txt").LastWriteTimeUtc
    

    或者为自己节省一些时间并使用可以为您执行此操作的 FTP 库/工具。

    例如使用WinSCP .NET assembly,您可以通过一次调用Session.SynchronizeDirectories 将整个本地文件夹与远程文件夹同步。或者您可以将同步限制为仅一组文件。

    # Load WinSCP .NET assembly
    Add-Type -Path "WinSCPnet.dll"
    
    # Setup session options
    $sessionOptions = New-Object WinSCP.SessionOptions
    $sessionOptions.Protocol = [WinSCP.Protocol]::Ftp
    $sessionOptions.HostName = "ftpsite.com"
    
    $session = New-Object WinSCP.Session
    
    # Connect
    $session.Open($sessionOptions)
    
    $result = $session.SynchronizeDirectories(
        [WinSCP.SynchronizationMode]::Remote, "C:\local\folder", "/remote/folder")
    $result.Check()
    

    要使用该程序集,只需将.NET assembly package 的内容提取到您的脚本文件夹。无需其他安装。

    该程序集不仅支持MDTM,还支持其他检索时间戳的替代方法。

    (我是 WinSCP 的作者)

    【讨论】:

    • 很好的答案。我没有利用您的 WinSCP,但您帖子中的早期行是完美的。响应的延迟是因为那是我完成脚本所花费的时间——不是这部分,而是逻辑的其他部分。你肯定回答了我的帖子 - 其余的都在我身上。
    猜你喜欢
    • 2018-09-24
    • 2011-11-16
    • 2020-04-04
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 2012-11-05
    • 1970-01-01
    相关资源
    最近更新 更多