在PowerShell中自动化安全FTP的最佳方法是什么?

时间:2008-11-05 14:46:54

标签: .net powershell ftp

我想使用PowerShell自动化FTP下载数据库备份文件。文件名包含日期,因此我不能每天运行相同的FTP脚本。有没有一种干净的方法来构建PowerShell或使用.Net框架?

更新我忘了提到这是通过安全的FTP会话。

9 个答案:

答案 0 :(得分:24)

经过一些实验,我想出了这种方法来自动化PowerShell中的安全FTP下载。此脚本运行Chilkat Software管理的public test FTP server。因此,您可以复制并粘贴此代码,它将无需修改即可运行。

$sourceuri = "ftp://ftp.secureftp-test.com/hamlet.zip"
$targetpath = "C:\hamlet.zip"
$username = "test"
$password = "test"

# Create a FTPWebRequest object to handle the connection to the ftp server
$ftprequest = [System.Net.FtpWebRequest]::create($sourceuri)

# set the request's network credentials for an authenticated connection
$ftprequest.Credentials =
    New-Object System.Net.NetworkCredential($username,$password)

$ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile
$ftprequest.UseBinary = $true
$ftprequest.KeepAlive = $false

# send the ftp request to the server
$ftpresponse = $ftprequest.GetResponse()

# get a download stream from the server response
$responsestream = $ftpresponse.GetResponseStream()

# create the target file on the local system and the download buffer
$targetfile = New-Object IO.FileStream ($targetpath,[IO.FileMode]::Create)
[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)

$targetfile.close()

我在这些链接上找到了很多有用的信息

如果要使用SSL连接,则需要添加行

$ftprequest.EnableSsl = $true
在调用GetResponse()之前

到脚本。有时您可能需要处理已过期的服务器安全证书(就像我不幸的那样)。 PowerShell Code Repository上有一个页面,其中包含执行此操作的代码段。前28行与下载文件最相关。

答案 1 :(得分:7)

取自here

$source = "ftp://ftp.microsoft.com/ResKit/win2000/dureg.zip"
$target = "c:\temp\dureg.zip"
$WebClient = New-Object System.Net.WebClient
$WebClient.DownloadFile($source, $target)

为我工作

答案 2 :(得分:4)

就PowerShell而言,/ n Software NetCmdlets包中包含FTP cmdlet(包括对两种安全FTP类型的支持),您可以非常轻松地使用它们。

答案 3 :(得分:2)

JAMS Job Scheduler提供了一些可以简化此任务的cmdlet。它有各种用于安全会话的FTP cmdlet以及用于将自然日期转换为.Net日期对象的日期cmdlet,例如“最后一天”:

JAMS Job Scheduler Cmdlets

答案 4 :(得分:1)

这并不像我希望的那么简单。我知道有三种选择。

1).Net - 您可以使用.Net框架在PS中执行此操作,但它涉及我不想在脚本中执行的原始套接字操作。如果我要去这条路线,那么我会将所有ftp垃圾包装到C#中的DLL中,然后使用来自powershell的DLL。

2)操作文件 - 如果您知道每天需要获取的文件名称模式,那么您可以使用PS打开ftp脚本并更改脚本中文件的名称。然后运行脚本。

3)将文本传输到FTP - 最后一个选项是使用powershell将信息传入和传出FTP会话。请参阅here

答案 5 :(得分:1)

这样的事情可行:

$bkdir = "E:\BackupsPWS" #backups location directory
$7Zip = 'C:\"Program Files"\7-Zip\7z.exe' #compression utility
$files_to_transfer = New-Object System.Collections.ArrayList #list of zipped files to be   transferred over FTP
$ftp_uri="myftpserver"
$user="myftpusername"
$pass="myftppassword"

#find .bak files not zipped yet, zip them, add them to the list to be transferrd
get-childitem -path $bkdir | Sort-Object length |
where { $_.extension -match ".(bak)" -and
-not (test-path ($_.fullname -replace "(bak)", "7z")) } |
foreach {
$zipfilename = ($_.fullname -replace "bak", "7z")
Invoke-Expression "$7Zip a $zipfilename $($_.FullName)"
$files_to_transfer.Add($zipfilename)
}

#find .bak files, if they've been zipped, delete the .bak file
get-childitem -path $bkdir |
where { $_.extension -match ".(bak)" -and
(test-path ($_.fullname -replace "(bak)", "7z")) } |
foreach { del $_.fullname }

#transfer each zipped file over FTP
foreach ($file in $files_to_transfer)
{
$webclient = New-Object System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($user,$pass) # FTP credentials
$ftp_urix = $ftp_uri + "/" + $file.Substring($bkdir.Length + 1) # ftp address where to transfer   the file
$uri=[system.URI] $ftp_urix
$webclient.UploadFile($uri, $file) #transfer the file
}

请检查:Powershell: compress backups and FTP transfer

答案 6 :(得分:1)

@Eric投票最多的自我解答正在起作用,但这是:

  • 效率低下,只有1KB缓冲区;
  • 不必要的重新实现,使用Stream.CopyTo可以轻松而高效地完成操作:
$fileUrl = "ftp://ftp.example.com/remote/path/file.zip"
$localFilePath = "C:\local\path\file.zip"

$downloadRequest = [Net.WebRequest]::Create($fileUrl)
$downloadRequest.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile
$downloadRequest.Credentials =
    New-Object System.Net.NetworkCredential("username", "password")
# Enable secure FTPS (FTP over TLS/SSL)
$downloadRequest.EnableSsl = $True

$sourceStream = $downloadRequest.GetResponse().GetResponseStream()
$targetStream = [System.IO.File]::Create($localFilePath)
$sourceStream.CopyTo($targetStream);

$sourceStream.Dispose()
$targetStream.Dispose()

有关上传,请参见Upload files with FTP using PowerShell

答案 7 :(得分:0)

我已成功使用Indy Project .NET库来执行FTP。并且......呃,看起来托管的.NET版本已经不再可用了。

答案 8 :(得分:0)

$ realdate =(Get-Date).ToString(“yyyyMMdd”)

$ path =“D:\ samplefolderstructure \ filename”+ $ realdate +“。msi”

ftps -f $ path -s:D:\ FTP.txt

ftp.txt是我们将所有连接信息保存到ftp服务器的方式。 ftps是我们明显使用的客户端,因此可能需要更改一些内容。但是,这应该可以帮助你实现这个想法。