27

我想使用 PowerShell 自动下载数据库备份文件。文件名包含日期,所以我不能每天都运行相同的 FTP 脚本。是否有一种内置于 PowerShell 或使用 .NET 框架的干净方法来执行此操作?

我想使用安全的 FTP 会话。

4

9 回答 9

24

经过一些实验后,我想出了这种在 PowerShell 中自动进行安全 FTP 下载的方法。该脚本在由 Chilkat Software 管理的公共测试 FTP 服务器上运行。因此,您可以复制并粘贴此代码,它无需修改即可运行。

$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 代码库中有一个页面,其中包含执行此操作的代码片段。前 28 行与下载文件最相关。

于 2008-11-06T14:41:12.050 回答
6

取自这里

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

这个对我有用。

于 2008-11-05T15:04:57.883 回答
3

就 PowerShell 而言,/n Software NetCmdlets包包括 FTP cmdlet(包括对两种安全 FTP 类型的支持),您可以很容易地为此使用它们。

于 2008-11-05T20:25:36.037 回答
1

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

JAMS 作业计划程序 Cmdlet

于 2011-04-07T00:49:41.723 回答
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()

如需上传,请参阅使用 PowerShell 通过 FTP 上传文件

于 2020-06-05T14:33:09.897 回答
0

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

  1. .NET - 您可以使用 .NET 框架在 PowerShell 中执行此操作,但它涉及我不想在脚本中执行的原始套接字操作。如果我要走这条路,那么我会将所有 FTP 垃圾打包到 C# 中的 DLL 中,然后使用 PowerShell 中的 DLL。

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

  3. 将文本通过管道传输到 FTP - 最后一个选项是使用 PowerShell 将信息通过管道传输到 FTP 会话中。见这里

于 2008-11-05T15:03:25.967 回答
0

像这样的东西可以工作:

$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:压缩备份和 FTP 传输

于 2012-05-16T16:25:04.750 回答
-1

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

于 2008-11-05T17:20:20.467 回答
-1
$realdate = (Get-Date).ToString("yyyyMMdd")

$path = "D:\samplefolderstructure\filename" + $realdate + ".msi"

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

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

于 2008-11-05T17:28:55.223 回答