What's the best way to automate secure FTP in PowerShell?

52,154

Solution 1

After some experimentation I came up with this way to automate a secure FTP download in PowerShell. This script runs off the public test FTP server administered by Chilkat Software. So you can copy and paste this code and it will run without modification.

$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()

I found a lot of helpful information at these links

If you want to use an SSL connection you need to add the line

$ftprequest.EnableSsl = $true

to the script before you call GetResponse(). Sometimes you may need to deal with a server security certificate that is expired (like I unfortunately do). There is a page at the PowerShell Code Repository that has a code snippet to do that. The first 28 lines are the most relevant for the purposes of downloading a file.

Solution 2

Taken from 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)

It works for me.

Solution 3

As far as PowerShell goes, the /n Software NetCmdlets package includes FTP cmdlets (including support for both secure FTP types) that you could use pretty easily for this.

Solution 4

The JAMS Job Scheduler offers some cmdlets that would make this task simple. It has a variety of FTP cmdlets for secure sessions as well as date cmdlets for converting natural dates into .NET date objects such as "Last day of month":

JAMS Job Scheduler Cmdlets

Solution 5

The most voted self-answer by @Eric is working, but it is:

  • inefficient with only 1KB buffer;
  • unnecessarily complicated with reimplementing, what can easily and more efficiently be done with 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()

For an upload, see Upload files with FTP using PowerShell.

Share:
52,154
Eric Ness
Author by

Eric Ness

Updated on July 25, 2021

Comments

  • Eric Ness
    Eric Ness almost 3 years

    I'd like to automate the FTP download of a database backup file using PowerShell. The file name includes the date so I can't just run the same FTP script every day. Is there a clean way to do this built into PowerShell or using the .NET framework?

    I want to use a secure FTP session.