Technology

How to upload files via FTP with PowerShell

powershell logo

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

How to use FTP in PowerShell

There are several ways to perform FTP transfers in PowerShell.

The easiest way is to use WebClient.UploadFile. PowerShell is an object-oriented scripting language, and you have full access to .NET standard libraries with New-Object. With this you can create a new 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 handle TLS/SSL encrypted requests, nor do “active” FTP transfers. Using FtpWebRequestcovered below, will solve this problem.

However, storing your username and password in a script is not recommended, especially if that script is committed to a shared Git repository. You can instead 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"

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

Advanced FTP transfers with PowerShell

If you need more control, you should use FtpWebRequest. This will support TLS transfers and also allow you to disable passive mode. The easiest way to use it is to open a file stream and copy it to the 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 and doesn’t read every byte, it has the advantage of working better with huge file transfers.

Sending SFTP transfers with Posh-SSH

SFTP is an alternative FTP protocol that works over SSH. It’s a bit trickier to use than regular FTP, because you can’t just send a username and password, and it’s not supported by native PowerShell.

You will need to install the Posh-SSH package to communicate via SFTP:

Install-Module -Name Posh-SSH

Then you can start a new session, using a new credential object. It works the same way as web request forwards, except you’ll also need to log off when it’s done.

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) }

Sending large files with a progress bar in PowerShell

Using File Stream CopyTo is simple, but for long transfers you may want some kind of progress tracking. It’s a bit tricky to add, since you’ll have to copy the feeds yourself, but works well 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()




Source link

Related Articles

Leave a Reply

Your email address will not be published.

Check Also
Close
Back to top button
%d bloggers like this:

Adblock Detected

Please consider supporting us by disabling your ad blocker