How to upload files via FTP using PowerShell – Yalla Match

File Transfer Protocol (FTP) is a common service used to transfer files between clients and servers. It is often useful to automate these file transfers, and PowerShell scripts can be useful to speed up this process.

How to use FTP in PowerShell

There are several different ways to perform FTP transfers in PowerShell.

The simplest is to use WebClient.UploadFile. PowerShell is an object-oriented scripting language, and you have full access to it .NET virtual libraries with New-Object. With this, you can create a new one WebClientSet its credentials, and upload a file.

$client = New-Object System.Net.WebClient
$client.Credentials = New-Object System.Net.NetworkCredential("username", "password")
$client.UploadFile("ftp://example.com/path/archive.zip", "C:archive.zip")

This will work fine, but will not be able to process requests encrypted with TLS/SSL, or perform “active” FTP transfers. Use FtpWebRequestCovered below, you will solve this problem.

It’s not a good idea to store your username and password in a script, especially if that script is bound to a shared Git repository. Alternatively you can set environment variables like FtpUsername and access it in the script.

function uploadToFTPServer($remote, $local) {
    $client = New-Object System.Net.WebClient
    $client.Credentials = New-Object System.Net.NetworkCredential($Env:FtpUsername, $Env:FtpPassword)
    $client.UploadFile($remote, $local)
}

uploadToFTPServer "ftp://example.com/path/archive.zip", "C:archive.zip"

Converting this to a function will also allow you to easily perform multiple transfers by calling the function with different parameters.

Advanced FTP Transfers Using PowerShell

If you need more control, you should use it FtpWebRequest. This will support TLS transfers, and also allow you to turn off passive mode. The easiest way to use it is to open a file stream and copy it to an FTP stream.

function uploadToFTPServer($remote, $local) {
    $request = [System.Net.FtpWebRequest]::Create($remote)
    $request.Credentials = New-Object System.Net.NetworkCredential($Env:FtpUsername, $Env:FtpPassword)
    $request.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile
    $request.UsePassive = $true

    $fileStream = [System.IO.File]::OpenRead($local)
    $ftpStream = $request.GetRequestStream()

    $fileStream.CopyTo($ftpStream)

    $ftpStream.Dispose()
    $fileStream.Dispose()
}

uploadToFTPServer "ftp://example.com/archive.zip" "C:archive.zip"

Since it uses file streams, not reading all bytes, this has the advantage of working better with huge file transfers.

Sending SFTP Transfers Using Posh-SSH

SFTP is an alternative FTP protocol that works over SSH. Using it is a bit more complicated than using regular FTP, as you can’t just send a username and password, and the native PowerShell doesn’t support it.

You will need to install a file Posh-SSH packet to communicate via SFTP:

Install-Module -Name Posh-SSH

Then you will be able to start a new session with a new credential object. This works the same as web request transfers, except that you will also need to close the session at the end.

Import-Module Posh-SSH

$Password = ConvertTo-SecureString $Env:FtpPassword -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential ($Env:FtpUsername, $Password)

$FilePath = "C:archive.zip"
$SftpPath="/folder"

$ThisSession = New-SFTPSession -ComputerName '1.2.3.4' -Credential $Credential

Set-SFTPFile -SessionId ($ThisSession).SessionId -LocalFile $FilePath -RemotePath $SftpPath
Get-SFTPSession | % { Remove-SFTPSession -SessionId ($_.SessionId) }

Send huge files with a progress bar in PowerShell

using a stream file CopyTo It’s simple, but for long transfers, you may want to kind of monitor the progress. This is a bit complicated to add, as you will have to copy the streams yourself, but it works fine with the following script:

$request = [Net.WebRequest]::Create("ftp://example.com/path/archive.zip")
$request.Credentials =
New-Object System.Net.NetworkCredential($Env:FtpUsername, $Env:FtpPassword)
$request.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile

$fileStream = [System.IO.File]::OpenRead("C:archive.zip")
$ftpStream = $request.GetRequestStream()

$buffer = New-Object Byte[] 10240
while (($read = $fileStream.Read($buffer, 0, $buffer.Length)) -gt 0)
{
    $ftpStream.Write($buffer, 0, $read)
    $pct = ($fileStream.Position / $fileStream.Length)
    Write-Progress `
        -Activity "Uploading" -Status ("{0:P0} complete:" -f $pct) `
        -PercentComplete ($pct * 100)
}

$ftpStream.Dispose()
$fileStream.Dispose()

Leave a Replay