Kuyrukta kullanılan AlexFTPS kütüphanesi Stion ölü gibi görünüyor (2011'den beri güncellenmedi).
Alternatif olarak, herhangi bir dış kütüphaneye olmadan bu uygulamaya deneyebilirsiniz. Ama ne yazık ki, ne .NET Framework ne de PowerShell bir dizindeki tüm dosyaları indirmek için herhangi bir açık desteğe sahip değil (sadece tekrarlayan dosya indirme izinleri).
Sen uygulamak zorunda olduğunu kendiniz:
- Liste uzak dizin
- Bıkmadan girişleri, dosya indirme (ve isteğe bağlı alt dizinleri içine recursing - vs. onları tekrar listelendiği)
Zor bölüm, alt dizinlerden dosyaları tanımlamaktır. Bunu, .NET çerçevesiyle (FtpWebRequest
veya WebClient
) taşınabilir bir şekilde yapmanın bir yolu yoktur. .NET çerçevesi, ne yazık ki, FTP protokolünde dosya öznitelikleriyle dizin listesini almak için tek taşınabilir yol olan MLSD
komutunu desteklemiyor. Ayrıca bkz. Checking if object on FTP server is file or directory.
Seçenekleriniz şunlardır:
- Eğer dizin tüm alt içermediğini biliyorsanız,
ListDirectory
yöntemi (NLST
FTP komutu) kullanmak ve sadece dosyaları gibi tüm "isimler" indirin.
- Dosya için başarısız olan ve dosya için başarılı olan bir dosya adı üzerinde bir işlem yapın (veya tersi). Yani "adını" indirmeyi deneyebilirsiniz.
LIST
(Şanslı olabilir ve spesifik durumda, (alt dizinleri yok ederken yani tüm dosyalarınızı bir uzantısı olan)
- girişini uzun dizin kullandığınız bir dosya adıyla bir dizinden dosya söyleyebilir command =
ListDirectoryDetails
yöntem) ve sunucuya özgü bir listeyi ayrıştırmayı deneyin. Birçok FTP sunucusu, girişin başında d
tarafından bir dizin belirlediğiniz * nix stili listesini kullanır. Ancak birçok sunucu farklı bir format kullanıyor. Aşağıdaki örnek bu yaklaşımı (* nix biçimi varsayarak) kullanır
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)
{
$line = $listReader.ReadLine()
$lines.Add($line) | 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 | Out-Null
}
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()
}
}
}
Kullanım gibi işlev: Kod
C# Download all files and subdirectories through FTP benim C# örnekten çevrilmiştir
$credentials = New-Object System.Net.NetworkCredential("user", "mypassword")
$url = "ftp://ftp.example.com/directory/to/download/"
DownloadFtpDirectory $url $credentials "C:\target\directory"
. Sunucu özgü dizin listeleme biçimleri ayrıştırma ile sorunları önlemek istiyorsanız
, MLSD
komutu ve/veya çeşitli LIST
listeleme çözümleme biçimlerinin destekleyen bir 3. parti kitaplığı kullanın. İdeal olarak, bir dizinden tüm dosyaları indirmeye veya yinelemeli indirmelere yönelik bir destekle.
WinSCP .NET assembly ile Örneğin
Session.GetFiles
tek bir çağrı ile tüm dizin indirebilirsiniz: sunucu tarafından destekleniyorsa
# 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:\target\directory\*").Check()
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
Dahili olarak, WinSCP,
MLSD
komutu kullanır. Değilse,
LIST
komutunu kullanır ve düzinelerce farklı liste biçimini destekler.
Session.GetFiles
method varsayılan olarak yinelemelidir.
(Ben WinSCP yazarı olduğum)
$ remotepickupdir = get-childitem c ise: o değişkeni kurar zaman \ Test -recurse, powershell o yolda tüm öğeleri almak için çalışacağız. Bu yüzden uzak öğeleri geri alamıyor çünkü bu noktada bir giriş bile olmadı. Kodunuz yanlış görünüyor. – BSAFH
Bu kabul edildi olarak işaretlenmemelidir. Bu soruya cevap vermiyor! –