$ftpServer = "ftp.example.com"
$username ="validUser"
$password ="myPassword"
$localToFTPPath = "C:\ToFTP"
$localFromFTPPath = "C:\FromFTP"
$remotePickupDir = "/Inbox"
$remoteDropDir = "/Outbox"
$SSLMode = [AlexPilotti.FTPS.Client.ESSLSupportMode]::ClearText
$ftp = new-object "AlexPilotti.FTPS.Client.FTPSClient"
$cred = New-Object System.Net.NetworkCredential($username,$password)
$ftp.Connect($ftpServer,$cred,$SSLMode) #Connect
$ftp.SetCurrentDirectory($remotePickupDir)
$ftp.GetFiles($localFromFTPPath, $false) #Get Files
这是我从FTP服务器导入文件的脚本
但是我不确定remotePickupDir
是什么,这个脚本是否正确?
答案 0 :(得分:22)
问题中使用的AlexFTPS库似乎已死(自2011年以来未更新)。
或者,您可以尝试在没有任何外部库的情况下实现此功能。但遗憾的是,.NET Framework和PowerShell都没有明确支持下载目录中的所有文件(只允许递归文件下载)。
你必须自己实现:
棘手的部分是识别子目录中的文件。使用.NET框架(FtpWebRequest
或WebClient
)以便携方式无法做到这一点。遗憾的是,.NET框架不支持MLSD
命令,这是在FTP协议中使用文件属性检索目录列表的唯一可移植方式。另请参阅Checking if object on FTP server is file or directory。
您的选择是:
ListDirectory
方法(NLST
FTP命令)并将所有“名称”下载为文件。LIST
command = ListDirectoryDetails
方法)并尝试解析特定于服务器的列表。许多FTP服务器使用* nix样式列表,您可以在条目的最开始通过d
标识目录。但是许多服务器使用不同的格式。以下示例使用此方法(假设为* 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)
{
$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()
}
}
}
使用如下功能:
$credentials = New-Object System.Net.NetworkCredential("user", "mypassword")
$url = "ftp://ftp.example.com/directory/to/download/"
DownloadFtpDirectory $url $credentials "C:\target\directory"
代码是从C# Download all files and subdirectories through FTP中的C#示例翻译而来。
如果要避免解析特定于服务器的目录列表格式的麻烦,请使用支持MLSD
命令和/或解析各种LIST
列表格式的第三方库。理想情况下,支持从目录下载所有文件,甚至是递归下载。
例如,使用WinSCP .NET assembly,只需拨打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:\target\directory\*").Check()
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
如果服务器支持,WinSCP在内部使用MLSD
命令。如果没有,它使用LIST
命令并支持许多不同的列表格式。
默认情况下,Session.GetFiles
method是递归的。
(我是WinSCP的作者)
答案 1 :(得分:6)
以下是将所有文件(带通配符或文件扩展名)从FTP站点下载到本地目录的完整工作代码。设置变量值。
#FTP Server Information - SET VARIABLES
$ftp = "ftp://XXX.com/"
$user = 'UserName'
$pass = 'Password'
$folder = 'FTP_Folder'
$target = "C:\Folder\Folder1\"
#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
}
答案 2 :(得分:5)
远程选择目录路径应该是您尝试访问的ftp服务器上的确切路径。 这是从服务器下载文件的脚本.. 您可以使用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)
}
答案 3 :(得分:1)
remotePickupDir
将是您要在ftp服务器上访问的文件夹。至于“这个脚本是否正确”,那么,它有效吗?如果它工作,那么它是正确的。如果它不起作用,请告诉我们您收到的错误消息或意外行为,我们将能够更好地为您提供帮助。
答案 4 :(得分:0)
基于Why does FtpWebRequest download files from the root directory? Can this cause a 553 error?,我编写了一个PowerShell脚本,该脚本可以通过TLS上的显式FTP从FTP服务器下载文件:
.animation(.spring(response: 0.5, dampingFraction: 0.30, blendDuration: 1), value: self.rotated)
答案 5 :(得分:0)
Invoke-WebRequest 可以下载 HTTP、HTTPS 和 FTP 链接。
$source = 'ftp://Blah.com/somefile.txt'
$target = 'C:\Users\someuser\Desktop\BlahFiles\somefile.txt'
$password = Microsoft.PowerShell.Security\ConvertTo-SecureString -String 'mypassword' -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList myuserid, $password
# Download
Invoke-WebRequest -Uri $source -OutFile $target -Credential $credential -UseBasicParsing
由于 cmdlet 使用 IE 解析,您可能需要 -UseBasicParsing 开关。测试以确保。
答案 6 :(得分:-1)
为了通过powerShell从FTP检索文件/文件夹我写了一些函数,你甚至可以从FTP中获取隐藏的东西。
获取未隐藏在特定文件夹中的所有文件的示例:
Get-FtpChildItem -ftpFolderPath "ftp://myHost.com/root/leaf/" -userName "User" -password "pw" -hidden $false -File
获取特定文件夹中所有文件夹(也是隐藏)的示例:
Get-FtpChildItem -ftpFolderPath"ftp://myHost.com/root/leaf/" -userName "User" -password "pw" -Directory
您只需复制以下模块中的功能,而无需安装第3个库: https://github.com/AstralisSomnium/PowerShell-No-Library-Just-Functions/blob/master/FTPModule.ps1
答案 7 :(得分:-1)
对不起,但是我发现所有答案都偏离了轨道。如果将powershell真正理解为外壳,则只需使用最喜欢的万无一失的本机ftp程序并完成它即可。明智的方法是为一个特定的任务提供一个好的工具,这意味着功能丰富的操作系统将提供广泛的命令行工具。 MS从来没有走过这条路,做最基础的工作仍然很痛苦。为什么不通过安装cygwin和ncftp来交换生态系统?