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 eld
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.