File Transfer (FTP and SFTP)



There are several cmdlets included in NetCmdlets that can be used for file transfer, such as Get/Send-FTP, Get/Send-SFTP, Get/Send-SCP, Get-HTTP, Get/Send-WebDAV, and more. The most commonly used file transfer methods are still FTP and SFTP.

The FTP cmdlets are Get-FTP and Send-FTP. These support both plaintext FTP and FTPS (FTP over SSL).

The SFTP cmdlets are Get-SFTP and Send-SFTP. These support SFTP (file transfer over SSH).

These cmdlets provide advanced features giving you the most flexibility. Examples include SSL and SSH support, multiple authentication modes, transfer resume, proxy/firewall support, etc.

Below is a basic example of using Get-FTP to download a file from ftp.microsoft.com and upload it to a local FTP server:

PS> Get-FTP -Server ftp.microsoft.com -User anonymous -Password JohnDoe@microsoft.com 
-LocalFile readme.txt -RemoteFile /deskapps/readme.txt PS> Send-FTP -Server YourServer -User test -Password test -LocalFile readme.txt
-RemoteFile MyFolder/readme.txt

Directory Listings

To list the contents of a directory, the List parameter can be set to a path on the remote server. Both the Get-FTP and Get-SFTP cmdlets operate in the same manner. To specify a filemask, set the RemoteFile parameter to a path and filemask. For instance:

  • FTP: Listing all .txt files in a directory

    PS> Get-FTP -User test -Password test -Server MyServer -List MyFolder/*.txt | 
    ForEach-Object { $_.FileName }
  • SFTP: Listing all .txt files in a directory
    PS> Get-SFTP -User test -Password test -Server MyServer -List MyFolder/*.txt | 
    ForEach-Object { $_.FileName }

SSL and SSH options

The Get-FTP and Send-FTP cmdlets support both plaintext and SSL connections (FTP and FTPS). By default a plaintext connection will be made. The Get-SFTP and Send-SFTP cmdlets support file transfer over SSH (SFTP).

Below is an example of using the cmdlets to create secure connections.

  • Plain FTP connection:
    PS> Get-FTP -Server myserver -User test -Password mypass
  • SSL connection:
    PS> Get-FTP -Server myserver -User test -Password mypass -ssl explicit

    The SSL parameter here can be set to either "Explicit" or "implicit". "Explicit SSL" is when a TCP connection is established, and an FTP command is sent (prior to authentication) explicitly telling the server to enter SSL mode. This is done on the same port as regular FTP connections (usually port 21). "Implicit SSL" occurs when SSL is assumed from the start by both parties, for this reason a separate port is typically used. You can specify the port through the Port parameter (usually port 990).

    An optional SSLAccept parameter may be specified to tell the cmdlet to automatically accept the SSL certificate presented by the server during the SSL handshake process. If this parameter is not specified, the cmdlet will prompt the user to accept the server certificate. If the SSLAccept parameter is used, it must be set to the base64 encoded public key of the trusted certificate (i.e. Get-FTP -Server myserver -Credential $testcred -SSL explicit -SSLAccept $mycert). After every connection the $SSLServerCertificate variable will be populated with the server's certificate.
    Below you will find an example of connecting to an FTP server with SSL and storing the server's certificate for later use.

    
    PS> Get-FTP -Server myserver -User test -Password test -SSL explicit
    PS> Set-Content c:\cert.txt $SSLServerCertificate.Encoded
    PS> $myCert = [System.IO.File]::ReadAllText("c:\cert.txt")
    PS> Get-FTP -Server myserver -User test -Password test -SSL explicit -SSLAccept $myCert
  • SSH connection:
    
    PS> Get-SFTP -Server myserver -User test -Password mypass

    In addition to SSH password authentication, as shown in the above example, public key authentication is also supported through the use of a set of -Cert* parameters used to point to a local certificate.

    An optional SSHAccept parameter may be specified to tell the cmdlet to automatically accept the host key presented by the server during the SSH handshake process. If this parameter is not specified, the cmdlet will prompt the user to accept the server host key. If the SSHAccept parameter is used, it will be set to the hex encoded fingerprint of the host key. For instance:

    PS> Get-FTP -Server myserver -User test -Password mypass -SSHAccept 59:52:C8:DB:C8:3A:FE:CF:9D:02:E3:31:3A:2C:11:E4

Transferring Files

The Get-FTP and Get-SFTP cmdlets allow you to download files from a remote FTP or SFTP server by specifying the remotefile parameter in addition to the connection parameters. If a RemoteFile is specified, the cmdlet will begin downloading the file to the client. If a LocalFile parameter is specified, the data will be written to that location, otherwise the cmdlet will attempt to write the LocalFile in the current directory using the same file name as the remote file.

Likewise, the Send-FTP and Send-SFTP cmdlets allow you to upload files to a remote FTP or SFTP server by specifying the LocalFile parameter. To set a custom name for the remote file, specify the RemoteFile parameter as well.

Examples:

Find all the local .txt files and upload them to a remote FTP server:

PS> Get-ChildItem *.txt | 
ForEach-Object { 
  Send-FTP -Server server -User test -Password test -LocalFile $($_.Name) 
-RemoteFile MyFolder/$($_.Name) }

Recursively upload the contents of a local directory:


param( 
    [string] $dir = "C:\temp\zip\", 
    [string] $myServer = "server",
    [string] $myUser = "test",
    [string] $myPassword = "test",
    [string] $remoteParentDir = "/Folder/temp/recursetest/" #an absolute path
)

$files = (Get-ChildItem $dir -Recurse)

#create a persistent connection
$myFTPConnection = Connect-FTP -Server $myServer -User $myUser -Password $myPassword

foreach ($file in $files) {
  $remfilename = $file.FullName.Replace($dir, "")
  $remfilename = $remfilename.Replace("\", "/")
  
  if ($file.Attributes -eq "Directory") {
    Send-FTP -Connection $myFTPConnection -MakeDirectory $($remoteParentDir + $remfilename.SubString(1))
  }
  else {
    Send-FTP -Connection $myFTPConnection -LocalFile $file.FullName -RemoteFile $($remoteParentDir + $remfilename)
  }
  Write-Host $remfilename
}  

Disconnect-FTP -Connection $myFTPConnection

Additional Examples

Find the files on a remote server that are larger than 10MB:

PS> Get-FTP -Server MyServer -User test -Password test -List *.* |
Where-Object { $_.FileSize -gt 10MB }

Delete a file on a remote FTP server:

PS> Remove-FTP -Server myserver -User test -Password test -RemoteFile filetodelete.txt

Calculate the number of bytes in the files of a remote server directory:

PS> Get-FTP -Server myserver -User test -Password test -List *.* |
Measure-Object -Property FileSize -Sum