目录
1. 前言
2. 遇见PSFTP
3. 初探PSFTP
4. 连接FTP
5. 使用PSFTP进行文件管理
5.1 添加/上传文件 - Add-FTPItem (Send-FTPItem)
使用举例:
5.2 获取目录下面的文件、子目录 - Get-FTPChildItem
使用举例:
5.3 下载文件 - Get-FTPItem(Receive-FTPItem)
使用举例:
5.4 获取文件大小 - Get-FTPItemSize
使用举例:
5.5 新建目录 - New-FTPItem
使用举例:
5.6 删除文件 - Remove-FTPItem
使用举例:
5.7 重命名文件或者目录 - Rename-FTPItem(Move-FTPItem)
使用举例:
5.8 检查文件或者目录是否存在 - Test-FTPItem
使用举例:
6. 总结
之前在【Azure - App Service】如何使用PowerShell一键部署前端代码到微软Azure云的App Service上_码农杰克的博客-CSDN博客
中提到在之前尝试部署前端代码到Azure云上时,曾尝试过使用FTP来操作。但是很不幸没有成功,不过倒是对PowerShell如何操作FTP搞明白了。 所以接下来对PowerShell操作FTP作一番记录,以备后用。
其实PowerShell本身并没了内置对FTP的支持,但是.net里面内置了FTP操作的类。当时在微软官方文档上看到了下面一段示例代码,主要就是演示如何通过PowerShell上传前端代码到Azure 的APP Service 上。PowerShell: Upload files using FTP - Azure App Service | Microsoft DocsLearn how to use Azure PowerShell to automate deployment and management of App Service. This sample shows how to upload files to an app using FTP.https://docs.microsoft.com/en-us/azure/app-service/scripts/powershell-deploy-ftp
$filePath=""
$webappname="mywebapp$(Get-Random)"
$location="West Europe"
# Create a resource group.
New-AzResourceGroup -Name myResourceGroup -Location $location
# Create an App Service plan in `Free` tier.
New-AzAppServicePlan -Name $webappname -Location $location `
-ResourceGroupName myResourceGroup -Tier Free
# Create a web app.
New-AzWebApp -Name $webappname -Location $location -AppServicePlan $webappname `
-ResourceGroupName myResourceGroup
# Get publishing profile for the web app
$xml = [xml](Get-AzWebAppPublishingProfile -Name $webappname `
-ResourceGroupName myResourceGroup `
-OutputFile null)
# Extract connection information from publishing profile
$username = $xml.SelectNodes("//publishProfile[@publishMethod=`"FTP`"]/@userName").value
$password = $xml.SelectNodes("//publishProfile[@publishMethod=`"FTP`"]/@userPWD").value
$url = $xml.SelectNodes("//publishProfile[@publishMethod=`"FTP`"]/@publishUrl").value
# Upload file
$file = Get-Item -Path $filePath
$uri = New-Object System.Uri("$url/$($file.Name)")
$request = [System.Net.FtpWebRequest]([System.net.WebRequest]::Create($uri))
$request.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile
$request.Credentials = New-Object System.Net.NetworkCredential($username,$password)
# Enable SSL for FTPS. Should be $false if FTP.
$request.EnableSsl = $true;
# Write the file to the request object.
$fileBytes = [System.IO.File]::ReadAllBytes($filePath)
$request.ContentLength = $fileBytes.Length;
$requestStream = $request.GetRequestStream()
try {
$requestStream.Write($fileBytes, 0, $fileBytes.Length)
}
finally {
$requestStream.Dispose()
}
Write-Host "Uploading to $($uri.AbsoluteUri)"
try {
$response = [System.Net.FtpWebResponse]($request.GetResponse())
Write-Host "Status: $($response.StatusDescription)"
}
finally {
if ($null -ne $response) {
$response.Close()
}
}
这段代码只是C#与PowerShell的混合编程,因为PowerShell本身支持内嵌C#代码,并且在PowerShell中可以直接使用C#库。其中就有一个[System.Net.FtpWebRequest],这个就是.net里内置的FTP操作类。感兴趣的同学请参考下面的连接。System.Net.FtpWebRequesthttps://docs.microsoft.com/en-us/dotnet/api/system.net.ftpwebrequest?view=net-6.0
一看上面的代码,我去,这玩意简单啊,封装几个方法就可以开始我的自动部署之旅了。
。。。等等,是不是已经有人帮我造好轮子了。于是又去PowerShell Gallery里面搜刮一番,果然轮子已经有了。
既然这样那就不客气了,拿来!
Install-Module -Name PSFTP
查看是否已经安装成功
Get-Module PSFTP -ListAvailable
接下来就可以开始我们的PowerShell FTP之旅了。
那么如何使用这个插件呢? 在使用之前先想想,平时使用ftp工具的时候是怎么个步骤?
是不是,先输入用户名密码点连接->上传,下载文件,删除创建文件,目录等。总之就是要先连接才能干事。
看看这个PSFTP工具里面都有些啥好东西:
Get-Command -Module PSFTP
里面一共10个Function, 3个Alias。3个Alias只是其中3个方法的别名。所以总共就是10个方法。至于这三个别名,好奇的看一下到底是那三个方法的别名:
跟猜想的差不多 。至于它代码怎么写的暂时先不关心。接下来就看看如何才能连接到FTP。
在上面的探索中一个命令引起了我的注意,那就是Set-FTPConnection。这个一看就是建立FTP连接的。
先看下如何使用:
> Get-Help Set-FTPConnection -Examples
NAME
Set-FTPConnection
SYNOPSIS
Set config to ftp Connection.
-------------------------- EXAMPLE 1 --------------------------
PS > Set-FTPConnection -Credentials userName -Server myftpserver.com
-------------------------- EXAMPLE 2 --------------------------
PS > $Credentials = Get-Credential
Set-FTPConnection -Credentials $Credentials -Server ftp://myftpserver.com -EnableSsl -ignoreCert -UsePassive
在最后看到有两个示例,尝试了一下第二个示例,因为Azure上的FTP是需要用户名密码的
$cre=Get-Credential
Set-FTPConnection -Credentials $cre -Server
但是悲催的是,用这种方式死活连不上Azure云。然后暴力的尝试了一下它的其它几个参数甚至是他们的组合:
[-EnableSsl] [-ignoreCert] [-KeepAlive] [-UseBinary] [-UsePassive]
最后发现是 -UsePassive 搞的鬼,一开始为什么没有往这个上面去想?主要是本人对ftp协议本身不甚了解,平时都是作为FTP的用户,哪管它是Active还是Passive?这也是FTP里面的两种连接模式,一个是主动模式,一个是被动模式。但是为啥要这样?这两者有啥区别?没时间去深究,除非我要在FTP上大有一番作为。感兴趣的读者可以去自行搜索,或者直接移步rfc959这个才是它的根。FILE TRANSFER PROTOCOL (FTP-rfc959)https://www.ietf.org/rfc/rfc959.txt
简单来讲就是主动模式下面,服务器会主动向FTP客户端发起连接,也就是你的电脑。这在一般的安全意识里面是不太靠谱的,因为我们的电脑都有防火墙(我假设)对这种外部来的不明连接都会打死。所以正常情况使用被动模式就行了,也就是说爷想连才连。但是我们平时使用的FTP工具它会自动尝试啊,谁关心是不是Passive。也不知道定协议的人是怎么想的。不过在局域网内部估计应该可以使用Active模式。所以想想应该也是有些历史原因的,也不能完全怪人家定协议的人。
扯远了,所以废话不多说,建立连接的有效命令如下,如果你的FTP服务器不在你的局域网里面的话。
$cre=Get-Credential
Set-FTPConnection -Credentials $cre -Server -Passive
接下来我们就可以看看怎么操作FTP上的东西了。
也可以使用Get-FTPConnection来查看是否有连接已经建立。
来一个个看下PSFTP是如何进行FTP操作的:
常用的主要是3个参数
-Path 服务器端路径,可以是相对路径也可以是绝对路径(这个是目录不是文件名,被坑好久)。如果不指定就把文件传在服务器端的当前路径。
那服务器端的当前路径是啥呢?就是你连接FTP时候指定的那个路径
-LocalPath 本地文件路径
-Overwrite 是否覆盖,如果不指定在遇到同名文件的时候会弹出确认框,如下图所示:
覆盖一个已经存在的文件:
这个和本地文件系统的Get-ChildItem很类似,但是区别是Get-FTPChildItem无法通过指定-File或者-Directory来指定返回的是文件还是目录。如果有这样的需求可以自己修改PSFTP的源码,PSFTP的源码也是通过[System.Net.FtpWebRequest]类来实现的。
主要参数:
-Path 指定目录,如果不指定就使用当前目录(FTP目录)。这个参数是使用最多的。
-Filter 设置过滤器,可以按照一定规则过滤返回结果
-Recurse 是否递归获取,也就是是否要获取子目录下面的信息
-Depth 递归深度
获取当前目录下面的文件和目录信息
只返回目录信息
递归返回所有信息
指定递归深度
主要参数:
-Path FTP服务器上的文件路径,可以是相对路径,也可以是绝对路径(FTP URI)
-LocalPath 本地文件路径,如果不指定默认为当前工作路径
-RecreateFolders 如果本地路径不存在可以使用这个命令自动创建目录
下载image.png到当前目录
Get-FTPItem image.png
下载image.png到指定目录
Get-FTPItem image.png -LocalPath D:\test
下载image.png到指定目录,如果指定目录不存在自动创建
Get-FTPItem image.png -LocalPath D:\test\1\2\3\4\5 -RecreateFolders
这个命令不常用,就不在这里赘述了。
这个命令主要用来创建目录的。
-Path 要创建目录的父路径,如果不指定就是当前目录
-Name 要创建目录的名字
当前目录创建子目录
New-FTPItem -Name testdir
指定目录创建子目录
New-FTPItem -Name testdir -Path ftp:///subdir
按理说这个命令应该可以删除文件或者目录(都提供-Recurse参数了),但是经过测试,只能删除文件。感兴趣的读者可以自己去尝试实现一下。
所以只需要用-Path参数指定要删除文件的路径就好了,可以是相对路径也可以是绝对路径。
重命名文件:
重命名目录:
按照作者给出的解释这个命令是要测试给定的路径是一个文件或者目录,但是实际测试的结果来看不管给的路径是文件还是目录。只要存在就返回File,不存在就抛错。什么鬼?我就想说作者你能不能走走心?
一个文件,一个目录返回结果都是File。好在不太需要这个命令,要不又要被误导不知几何。如有需要的小伙伴可以去需改它的源码让其支持。
本文介绍了PowerShell操作FTP的原理,主要是使用.net 提供的类来访问FTP。主要介绍PSFTP这个插件的详细使用以及一些使用上的注意事项。