Saltar al contenido

PowerShell Conéctese al servidor FTP y obtenga archivos

Si encuentras algo que no comprendes nos puedes dejar un comentario y te ayudaremos rápidamente.

Solución:

La biblioteca AlexFTPS utilizada en la pregunta parece estar muerta (no se actualizó desde 2011).


Sin bibliotecas externas

Puede intentar implementar esto sin ninguna biblioteca externa. Pero desafortunadamente, ni .NET Framework ni PowerShell tienen soporte explícito para descargar todos los archivos en un directorio (deje solo descargas de archivos recursivas).

Tienes que implementarlo tú mismo:

  • Lista del directorio remoto
  • Itere las entradas, descargue archivos (y, opcionalmente, vuelva a clasificarlos en subdirectorios, enumerándolos nuevamente, etc.)

La parte complicada es identificar archivos de subdirectorios. No hay forma de hacerlo de forma portátil con .NET framework (FtpWebRequest o WebClient). Lamentablemente .NET framework no es compatible con MLSD comando, que es la única forma portátil de recuperar la lista de directorios con el archivo attributes en protocolo FTP. Consulte también Comprobación de si el objeto en el servidor FTP es un archivo o directorio.

Tus opciones son:

  • Si sabe que el directorio no contiene ningún subdirectorio, utilice la ListDirectory métodoNLST Comando FTP) y simplemente descargue todos los “nombres” como archivos.
  • Realice una operación en un nombre de archivo que seguramente fallará para el archivo y tendrá éxito para los directorios (o viceversa). Es decir, puede intentar descargar el “nombre”.
  • Puede tener suerte y, en su caso específico, puede distinguir un archivo de un directorio por un nombre de archivo (es decir, todos sus archivos tienen una extensión, mientras que los subdirectorios no)
  • Utiliza una lista de directorio larga (LIST comando = ListDirectoryDetails método) e intente analizar una lista específica del servidor. Muchos servidores FTP utilizan listas de estilo * nix, donde se identifica un directorio por el d al principio de la entrada. Pero muchos servidores usan un formato diferente. El siguiente ejemplo usa este enfoque (asumiendo el formato * nix)
function DownloadFtpDirectory($url, $credentials, $localPath)

    $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)
     Out-Null
    
    $listReader.Dispose()
    $listStream.Dispose()
    $listResponse.Dispose()

    foreach ($line in $lines)
    
        $tokens = $line.Split(" ", 9, [StringSplitOptions]::RemoveEmptyEntries)
        $name = $tokens[8]
        $permissions = $tokens[0]

        $localFilePath = Join-Path $localPath $name
        $fileUrl = ($url + $name)

        if ($permissions[0] -eq 'd')
        
            if (!(Test-Path $localFilePath -PathType container))
            
                Write-Host "Creating directory $localFilePath"
                New-Item $localFilePath -Type directory 

            DownloadFtpDirectory ($fileUrl + "/") $credentials $localFilePath
        
        else
        
            Write-Host "Downloading $fileUrl to $localFilePath"

            $downloadRequest = [Net.WebRequest]::Create($fileUrl)
            $downloadRequest.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile
            $downloadRequest.Credentials = $credentials

            $downloadResponse = $downloadRequest.GetResponse()
            $sourceStream = $downloadResponse.GetResponseStream()
            $targetStream = [System.IO.File]::Create($localFilePath)
            $buffer = New-Object byte[] 10240
            while (($read = $sourceStream.Read($buffer, 0, $buffer.Length)) -gt 0)
            
                $targetStream.Write($buffer, 0, $read);
            
            $targetStream.Dispose()
            $sourceStream.Dispose()
            $downloadResponse.Dispose()
        
    

Utilice la función como:

$credentials = New-Object System.Net.NetworkCredential("user", "mypassword") 
$url = "ftp://ftp.example.com/directory/to/download/"
DownloadFtpDirectory $url $credentials "C:targetdirectory"

El código se traduce de mi ejemplo de C # en C # Descargue todos los archivos y subdirectorios a través de FTP.


Usando una biblioteca de terceros

Si desea evitar problemas al analizar los formatos de lista de directorios específicos del servidor, utilice una biblioteca de terceros que admita la MLSD comando y / o análisis de varios LIST formatos de listado. E idealmente con un soporte para descargar todos los archivos de un directorio o incluso descargas recursivas.

Por ejemplo, con el ensamblaje de WinSCP .NET, puede descargar el directorio completo con una sola llamada a Session.GetFiles:

# Load WinSCP .NET assembly
Add-Type -Path "WinSCPnet.dll"

# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property @
    Protocol = [WinSCP.Protocol]::Ftp
    HostName = "ftp.example.com"
    UserName = "user"
    Password = "mypassword"


$session = New-Object WinSCP.Session

try

    # Connect
    $session.Open($sessionOptions)

    # Download files
    $session.GetFiles("/directory/to/download/*", "C:targetdirectory*").Check()

finally

    # Disconnect, clean up
    $session.Dispose()
    

Internamente, WinSCP usa el MLSD comando, si lo admite el servidor. Si no, usa el LIST comando y admite docenas de formatos de listas diferentes.

los Session.GetFiles El método es recursivo por defecto.

(Soy el autor de WinSCP)

Aquí está el código de trabajo completo para descargar todos los archivos (con comodín o extensión de archivo) desde el sitio FTP al directorio local. Establezca los valores de las variables.

    #FTP Server Information - SET VARIABLES
    $ftp = "ftp://XXX.com/" 
    $user = 'UserName' 
    $pass = 'Password'
    $folder = 'FTP_Folder'
    $target = "C:FolderFolder1"

    #SET CREDENTIALS
    $credentials = new-object System.Net.NetworkCredential($user, $pass)

    function Get-FtpDir ($url,$credentials) 
        $request = [Net.WebRequest]::Create($url)
        $request.Method = [System.Net.WebRequestMethods+FTP]::ListDirectory
        if ($credentials)  $request.Credentials = $credentials 
        $response = $request.GetResponse()
        $reader = New-Object IO.StreamReader $response.GetResponseStream() 
        while(-not $reader.EndOfStream) 
            $reader.ReadLine()
        
        #$reader.ReadToEnd()
        $reader.Close()
        $response.Close()
    

    #SET FOLDER PATH
    $folderPath= $ftp + "/" + $folder + "/"

    $files = Get-FTPDir -url $folderPath -credentials $credentials

    $files 

    $webclient = New-Object System.Net.WebClient 
    $webclient.Credentials = New-Object System.Net.NetworkCredential($user,$pass) 
    $counter = 0
    foreach ($file in ($files | where $_ -like "*.txt"))
        $source=$folderPath + $file  
        $destination = $target + $file 
        $webclient.DownloadFile($source, $target+$file)

        #PRINT FILE NAME AND COUNTER
        $counter++
        $counter
        $source
    

La ruta del directorio de selección remota debe ser la ruta exacta en el servidor ftp al que está intentando acceder .. aquí está el script para descargar archivos del servidor .. puede agregar o modificar con SSLMode ..

#ftp server 
$ftp = "ftp://example.com/" 
$user = "XX" 
$pass = "XXX"
$SetType = "bin"  
$remotePickupDir = Get-ChildItem 'c:test' -recurse
$webclient = New-Object System.Net.WebClient 

$webclient.Credentials = New-Object System.Net.NetworkCredential($user,$pass)  
foreach($item in $remotePickupDir) 
    $uri = New-Object System.Uri($ftp+$item.Name) 
    #$webclient.UploadFile($uri,$item.FullName)
    $webclient.DownloadFile($uri,$item.FullName)

Sección de Reseñas y Valoraciones

Recuerda algo, que tienes la opción de aclarar si descubriste tu dilema en el momento justo.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *