【问题标题】:Overwrite ftp files using powershell使用 powershell 覆盖 ftp 文件
【发布时间】:2019-02-15 21:48:15
【问题描述】:

问题是我的代码没有覆盖所有文件

我之前使用过这个脚本,它确实会上传文件并覆盖其中一些文件,但不会覆盖所有文件。

# Get publishing profile for the web app
$webappname = "sib"
$resourceGroup = "sib2"
$appdirecotry = "c:\temp\sib"
$xml = [xml](Get-AzureRmWebAppPublishingProfile -Name $webappname `
-ResourceGroupName $resourceGroup `
-OutputFile null)
$xml = [xml]$xml
# Extract connection information from publishing profile
$username = $xml.SelectNodes("//publishProfile[@publishMethod=`"FTP`"]/@userName").value
$password = $xml.SelectNodes("//publishProfile[@publishMethod=`"FTP`"]/@userPWD").value
$url = $xml.SelectNodes("//publishProfile[@publishMethod=`"FTP`"]/@publishUrl").value
Write-Host "Set a virtual application"
Set-Location $appdirectory
$webclient = New-Object -TypeName System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($username,$password)
$files = Get-ChildItem -Path $appdirectory -Recurse #| Where-Object{!($_.PSIsContainer)}
foreach ($file in $files)
{
    $relativepath = (Resolve-Path -Path $file.FullName -Relative).Replace('\', '/')
    $uri = New-Object System.Uri("$url/$relativepath")
    if($file.PSIsContainer)
    {
        $uri.AbsolutePath + "is Directory"
        $ftprequest = [System.Net.FtpWebRequest]::Create($uri);
        $ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::MakeDirectory
        $ftprequest.UseBinary = $true
        #$ftprequest.UsePassive = $true
        #$ftprequest.KeepAlive = $false

        $ftprequest.Credentials = New-Object System.Net.NetworkCredential($username,$password)

        $response = $ftprequest.GetResponse();
        $response.StatusDescription
        continue
    }
    "Uploading to " + $uri.AbsoluteUri
    $webclient.UploadFile($uri, $file.FullName)
} 
$webclient.Dispose()

它不会覆盖所有文件

【问题讨论】:

  • WebClient.UploadFile 方法在内部使用了FTP STOR 命令。因此它会理想地替换文件。您是否可以尝试添加异常处理块或日志,只是为了查看您的 URI 是否正确,因为有时通过组合 BaseAddress 生成的 URI 是无效的,它会引发 WebException。
  • Mohit 我试过了。它会覆盖大部分文件。但很少有文件没有被覆盖
  • 另外,它里面有目录,所以它首先通过一个不可用的错误文件创建目录,然后在目录之后,它会抛出登录问题,然后再次登录并上传剩余的文件。
  • 问题是那些目录已经存在。所以这就是它抛出异常的原因。

标签: azure powershell teamcity


【解决方案1】:

我必须在 CI/CD 流程中使用上述代码。所以如果是第一次做上面的脚本没问题,但是在ftp的覆盖场景下它就不能正常工作了。

如果我必须覆盖,我的脚本会改变。所以我现在有 2 个脚本。一个用于第一次环境,一个用于覆盖环境

而不是覆盖脚本中的以下内容

Set-Location $appdirectory
$webclient = New-Object -TypeName System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($username,$password)
$files = Get-ChildItem -Path $appdirectory -Recurse #| Where-Object{!($_.PSIsContainer)}
     foreach ($file in $files)
    {
        $relativepath = (Resolve-Path -Path $file.FullName -Relative).Replace('\', '/')
        $uri = New-Object System.Uri("$url/$relativepath")
        if($file.PSIsContainer)
        {
            $uri.AbsolutePath + "is Directory"
            $ftprequest = [System.Net.FtpWebRequest]::Create($uri);
            $ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::MakeDirectory
            $ftprequest.UseBinary = $true
            #$ftprequest.UsePassive = $true
            #$ftprequest.KeepAlive = $false

            $ftprequest.Credentials = New-Object System.Net.NetworkCredential($username,$password)

            $response = $ftprequest.GetResponse();
            $response.StatusDescription
            continue
        }
        "Uploading to " + $uri.AbsoluteUri
        $webclient.UploadFile($uri, $file.FullName)
    } 
    $webclient.Dispose()

我在覆盖脚本中使用以下内容

    Set-Location $appdirectory
$webclient = New-Object -TypeName System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($username,$password)
$files = Get-ChildItem -Path $appdirectory -Recurse | Where-Object{!($_.PSIsContainer)}
foreach ($file in $files)
{
    $relativepath = (Resolve-Path -Path $file.FullName -Relative).Replace(".\", "").Replace('\', '/')
    $uri = New-Object System.Uri("$url/$relativepath")
    "Uploading to " + $uri.AbsoluteUri
    $webclient.UploadFile($uri, $file.FullName)
} 
$webclient.Dispose()

上面的工作就像覆盖场景的魅力。但是让我确认一下,这在第一次设置中不起作用。如果你第一次尝试,它会抛出 550 错误。

【讨论】:

    【解决方案2】:

    这样会更好。

    function DeleteFtpFolder($url, $credentials)
    {
        $listRequest = [Net.WebRequest]::Create($url)
        $listRequest.Method = [System.Net.WebRequestMethods+FTP]::ListDirectoryDetails
        $listRequest.Credentials = $credentials
    
        $lines = New-Object System.Collections.ArrayList
    
        $listResponse = $listRequest.GetResponse()
        $listStream = $listResponse.GetResponseStream()
        $listReader = New-Object System.IO.StreamReader($listStream)
    
        while (!$listReader.EndOfStream)
        {
            $line = $listReader.ReadLine()
            $lines.Add($line) | Out-Null
        }
    
        $listReader.Dispose()
        $listStream.Dispose()
        $listResponse.Dispose()
    
        foreach ($line in $lines)
        {
            $tokens = $line.Split(" ", 5, [System.StringSplitOptions]::RemoveEmptyEntries)
    
            $type = $tokens[2]
            $name = $tokens[3]
            $fileUrl = ($url + "/" + $name)
    
            if ($type -eq "<DIR>")
            {
                Write-Host "Found folder: $name"
    
                DeleteFtpFolder $fileUrl $credentials
    
                Write-Host "Deleting folder: $name"
                $deleteRequest = [Net.WebRequest]::Create($fileUrl)
                $deleteRequest.Credentials = $credentials
                $deleteRequest.Method = [System.Net.WebRequestMethods+FTP]::RemoveDirectory
                $deleteRequest.GetResponse() | Out-Null
            }
            else 
            {
                $fileUrl = ($url + "/" + $name)
                Write-Host "Deleting file: $name"
    
                $deleteRequest = [Net.WebRequest]::Create($fileUrl)
                $deleteRequest.Credentials = $credentials
                $deleteRequest.Method = [System.Net.WebRequestMethods+FTP]::DeleteFile
                $deleteRequest.GetResponse() | Out-Null
            }
        }
    }
    
    $credentials = New-Object System.Net.NetworkCredential($username, $password)
    DeleteFtpFolder $url $credentials
    
    
    Set-Location $appdirectory
    $webclient = New-Object -TypeName System.Net.WebClient
    $webclient.Credentials = New-Object System.Net.NetworkCredential($username,$password)
    $files = Get-ChildItem -Path $appdirectory -Recurse #| Where-Object{!($_.PSIsContainer)}
    foreach ($file in $files)
    {
        $relativepath = (Resolve-Path -Path $file.FullName -Relative).Replace('\', '/')
        $uri = New-Object System.Uri("$url/$relativepath")
        if($file.PSIsContainer)
        {
            $uri.AbsolutePath + "is Directory"
            $ftprequest = [System.Net.FtpWebRequest]::Create($uri);
            $ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::MakeDirectory
            $ftprequest.UseBinary = $true
            #$ftprequest.UsePassive = $true
            #$ftprequest.KeepAlive = $false
    
            $ftprequest.Credentials = New-Object System.Net.NetworkCredential($username,$password)
    
            $response = $ftprequest.GetResponse();
            $response.StatusDescription
            continue
        }
        "Uploading to " + $uri.AbsoluteUri
        $webclient.UploadFile($uri, $file.FullName)
    } 
    $webclient.Dispose()
    

    【讨论】:

    • 在我的情况下 url 是站点根目录,如果要添加文件夹名称,请像这样添加文件夹名称: $foldertodelete = $url + "/foldertodelete" 传递 $foldertodelete 而不是 $url 以删除文件夹从ftp
    猜你喜欢
    • 1970-01-01
    • 2015-01-25
    • 2012-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    相关资源
    最近更新 更多