Using Powershell to perform ftp uploads

by Mikael Henriksson 11. July 2010 23:58

This is not so much for informational purposes as it is for safe keeping

. 'x:\path-to\ftp-tools.ps1'
$server = 'ftp.domain.com'
$dir = 'C:\Users\Public\Pictures\Sample Pictures'
$pass = ConvertTo-SecureString "******" -AsPlainText -Force
$cred = new-object `
 	-typename System.Management.Automation.PSCredential -argumentlist "*******", $pass

upload-directory `
 -server $server `
 -dir $dir `
 -overwrite $true `
 -cred $cred
function upload-directory {
  param([string] $server = $( Throw "You must specify an FTP server to logon to."),
	 [string] $dir = $( Throw "You must specify a local directory to upload (ie, C:\Testing\FTPTest\)"),
	 [switch] $overwrite = $false,
	 [System.Management.Automation.PSCredential] $cred = $( Throw "You must provide credentials with which to logon to the FTP server.") ) 
        
  $files = (get-childitem $dir -r)

  foreach ($file in $files) {
    $remfilename = $file.FullName.Replace($dir, "")
    $remfilename = $remfilename.Replace("\", "/")
    if ($file.Attributes.ToString().IndexOf("Directory") -ge 0) {
  	  try
  	  {
      	send-ftp -server $server -cred $cred
      }
      catch {} #if the directory already exists, ignore the error
    }
    else {
      send-ftp `
	  	-Server $server `
		-LocalFile $file.FullName `
		-Path "/account/zoolutions.se/Test" `
		-RemoteFile $remfilename `
		-Credentials $cred `
		-Overwrite $true
    }
  }
}
function send-ftp {

	param([string] $server = $( Throw "You must specify an FTP server to logon to."),
		[string] $dir = $( Throw "You must specify a local directory to upload (ie, C:\Testing\FTPTest\)"),
		[switch] $overwrite = $(Throw "Must select wheter to overwrite existing files"),
		[System.Management.Automation.PSCredential] $credentials = $(Get-Credential),
		[Parameter(ValueFromPipeline=$true)] $LocalFile = $( Throw "You must specify an FTP server to logon to."),  
		[string] $path = $( Throw "You must specify an FTP server to logon to."),  
		[string] $remoteFile = $(Split-Path $LocalFile -Leaf), 
		[int] $parentProgressId = -1,
		[string] $progressActivity = "Uploading $LocalFile" )
	  
	## Assert the existence of the file in question
	if( -not (Test-Path $LocalFile) ) {
		Throw "File '$LocalFile' does not exist!"
	}

	## Create the server string (and make sure it uses forward slashes and ftp://)
	$upload = "ftp://" + $Server + ( Join-Path (Join-Path "//" $Path) $RemoteFile ) -replace "\\", "/"
	#$Upload = $upload
	$total = (gci $LocalFile).Length

	Write-Debug $upload
	## Create FTP request
	$request = [Net.FtpWebRequest]::Create($upload)

	## NOTE: we do not create a folder here...
	# [System.Net.WebRequestMethods+Ftp]::MakeDirectory
	$request.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile
	$request.Credentials = $Credentials.GetNetworkCredential()
	$request.UsePassive = $true
	$request.UseBinary = $true
	$request.KeepAlive = $false

	try {
		## Load the file
		$read = [IO.File]::OpenRead( (Convert-Path $LocalFile) )
		$write = $request.GetRequestStream();
		
		$buffer = new-object byte[] 20KB
		$offset = 0
		$progress = 0

		do {
		$offset = $read.Read($buffer, 0, $buffer.Length)
		$progress += $offset
		$write.Write($buffer, 0, $offset);
		Write-Progress $ProgressActivity "Uploading" -Percent ([int]($progress/$total * 100)) -Parent $ParentProgressId
		} while($offset -gt 0)

	} finally {
		Write-Debug "Closing Handles"
		$read.Close()
		$write.Close()
	}
}

Tags:

PowerShell

blog comments powered by Disqus

About the author

Life architect specialized in programming