1
votes

So in my powershell script when it starts up it polls a ftp server and downloads any files that aren't in the local folder. The problem is when it gets to a folders it downloads them as files. this is my code for checking for new files:

$LocFolder = 'C:\EMSDropBox\*'
Remove-Item $LocFolder
$ftprequest = [System.Net.FtpWebRequest]::Create("ftp://NZHQFTP1/tbarnes")
$ftprequest.Proxy = $null
$ftprequest.KeepAlive = $false
$ftprequest.TimeOut = 10000000
$ftprequest.UsePassive = $False
$ftprequest.Credentials = New-Object System.Net.NetworkCredential("tbarnes", "Static_flow2290") 
$ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectory

$FTPResponse = $ftprequest.GetResponse()
$ResponseStream = $FTPResponse.GetResponseStream()
$FTPReader = New-Object System.IO.Streamreader($ResponseStream)
$filename = $FTPReader.ReadLine()
while($filename -ne $null)
{
    try
    {
        if((Test-Path ("C:\emsdropbox\"+$filename)) -ne $true)
        {
            downloadFtp($filename)
        }
        $filename = $FTPReader.ReadLine()
    }
    catch
    {
        Write-Host $_
    }
}
$FTPReader.Close()
$FTPResponse.Close()
$ResponseStream.Close()

and this is the downloadFtp function:

     # FTP Config
$FTPHost = "****"
$Username = "******"
$Password = "*********"
$FTPFile = $file

# FTP Log File Url
$FTPFileUrl = "ftp://" + $FTPHost + "/tbarnes/" + $FTPFile

    # Create FTP Connection
$FTPRequest = [System.Net.FtpWebRequest]::Create("$FTPFileUrl") 
$FTPRequest.Credentials = New-Object System.Net.NetworkCredential($Username, $Password) 
$FTPRequest.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile
$FTPRequest.UsePassive = $false
$FTPRequest.UseBinary = $true
$FTPRequest.KeepAlive = $false
$targetfile = New-Object IO.FileStream (("C:\emsdropbox\"+$file),[IO.FileMode]::Create)
# Get FTP File
$FTPResponse = $FTPRequest.GetResponse()
$ResponseStream = $FTPResponse.GetResponseStream()
$FTPReader = New-Object -typename System.IO.StreamReader -ArgumentList $ResponseStream
[byte[]]$readbuffer = New-Object byte[] 1024

#loop through the download stream and send the data to the target file
do{
    $readlength = $ResponseStream.Read($readbuffer,0,1024)
    $targetfile.Write($readbuffer,0,$readlength)
}
while ($readlength -ne 0)
$FTPReader.Close()

Im not sure why it wont pull them down as folders so any help or pointers would be great!

1

1 Answers

1
votes

The FTP methods don't support downloading of folders, or recursion, by themselves, so there's no other way I can think of doing this but what I've suggested below.

Change the method so you can differentiate between files and directories and handle them accordingly.

Change $ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectory to $ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails

Which will list in this format:

-rwxrwxrwx   1 owner    group          277632 Mar  4 17:15 xml_socket.log.rar

Directories will have a d in place of the - at the start of the line.

Here is an amended try block that will match only files so you can pass to the downloadFtp function:

    try
{
    if(!($filename -match '^d')){if((Test-Path ("C:\emsdropbox\"+$filename.Split(" ")[8])) -ne $true)
    {
        downloadFtp(($filename -split '\s+')[8])
    }}
    $filename = $FTPReader.ReadLine()
}

If you want to then get a list of directories, use the following try block against the same ftpresponse stream and for each, ListDirectoryDetails to get the list of files in each directory to process them:

    try
{
    if($filename -match '^d'){if((Test-Path ("C:\emsdropbox\"+$filename.Split(" ")[8])) -ne $true)
    {
        listdir(($filename -split '\s+')[8])
    }}
    $filename = $FTPReader.ReadLine()
}

You may also have to create the local directories too which you can do in powershell as follows:

New-Item c:\emsdropbox\newdir -type directory