Add-FTPItem.ps1
Function Add-FTPItem { <# .SYNOPSIS Send file to specific ftp location. .DESCRIPTION The Add-FTPItem cmdlet send file to specific location on ftp server. .PARAMETER Path Specifies a path to ftp location. .PARAMETER LocalPath Specifies a local path. .PARAMETER BufferSize Specifies size of buffer. Default is 20KB. .PARAMETER Session Specifies a friendly name for the ftp session. Default session name is 'DefaultFTPSession'. .PARAMETER Overwrite Overwrite item on remote location. .EXAMPLE PS> Add-FTPItem -Path "/myfolder" -LocalPath "C:\myFile.txt" Dir : - Right : rw-r--r-- Ln : 1 User : ftp Group : ftp Size : 82033 ModifiedDate : Aug 17 12:27 Name : myFile.txt .EXAMPLE PS> Get-ChildItem "C:\Folder" | Add-FTPItem .NOTES Author: Michal Gajda Blog : http://commandlinegeeks.com/ .LINK Get-FTPChildItem #> [CmdletBinding( SupportsShouldProcess=$True, ConfirmImpact="Low" )] Param( [String]$Path = "", [parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true)] [Alias("FullName")] [String]$LocalPath, [Int]$BufferSize = 20KB, $Session = "DefaultFTPSession", [Switch]$Overwrite = $false, [String]$StartPath ) Begin { if($Session -isnot [String]) { $CurrentSession = $Session } else { $CurrentSession = Get-Variable -Scope Global -Name $Session -ErrorAction SilentlyContinue -ValueOnly } if($CurrentSession -eq $null) { Write-Warning "Cannot find session $Session. First use Set-FTPConnection to config FTP connection." Break Return } } Process { Write-Debug $LocalPath if(Test-Path $LocalPath) { $LocalItem = Get-Item $LocalPath $ItemName = ($LocalItem).Name Write-Debug "Native path: $Path" if($Path -match "ftp://") { $RequestUri = $Path Write-Debug "Use original path: $RequestUri" } else { $RequestUri = $CurrentSession.RequestUri.OriginalString+"/"+$Path Write-Debug "Add ftp:// at start: $RequestUri" } if($LocalItem -is [System.IO.DirectoryInfo]) { if($CurrentSession.StartPath -eq "") { if($StartPath) { $CurrentSession.StartPath = $StartPath } else { $CurrentSession.StartPath = (Split-Path $LocalItem.FullName -Parent) -replace "\\","\\" } } $StartLocalPath = $CurrentSession.StartPath $PartLocalPath = $LocalPath -replace $StartLocalPath $RemotePath = $PartLocalPath -replace "\\","/" $RequestUri = $RequestUri+"/"+$RemotePath $RequestUri = $RequestUri -replace $ItemName $RequestUri = [regex]::Replace($RequestUri, '/$', '') $RequestUri = [regex]::Replace($RequestUri, '/+', '/') $RequestUri = [regex]::Replace($RequestUri, '^ftp:/', 'ftp://') Try { New-FTPItem -Path $RequestUri -Name $ItemName } Catch { Write-Debug "Probably folder $ItemName exist in path $RequestUri" } } else { if($CurrentSession.StartPath -eq "") { if($StartPath) { $CurrentSession.StartPath = $StartPath } else { $CurrentSession.StartPath = (Split-Path $LocalItem.FullName -Parent) -replace "\\","\\" } } $StartLocalPath = $CurrentSession.StartPath $PartLocalPath = $LocalPath -replace $StartLocalPath $RemotePath = $PartLocalPath -replace "\\","/" $RequestUri = $RequestUri+"/"+$RemotePath $RequestUri = [regex]::Replace($RequestUri, '/$', '') $RequestUri = [regex]::Replace($RequestUri, '/+', '/') $RequestUri = [regex]::Replace($RequestUri, '^ftp:/', 'ftp://') Write-Debug "Remove additonal slash: $RequestUri" if ($pscmdlet.ShouldProcess($RequestUri,"Send item: '$LocalPath' in ftp location")) { [System.Net.FtpWebRequest]$Request = [System.Net.WebRequest]::Create($RequestUri) $Request.Credentials = $CurrentSession.Credentials $Request.EnableSsl = $CurrentSession.EnableSsl $Request.KeepAlive = $CurrentSession.KeepAlive $Request.UseBinary = $CurrentSession.UseBinary $Request.UsePassive = $CurrentSession.UsePassive Try { [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$CurrentSession.ignoreCert} $SendFlag = 1 if($Overwrite -eq $false) { $FileSize = Get-FTPItemSize -Path $RequestUri -Session $Session -Silent if($FileSize -gt 0) { $FileSize = Get-FTPItemSize -Path $RequestUri -Session $Session -Silent $Title = "A File name: $ItemName already exists in this location." $Message = "What do you want to do?" $ChoiceOverwrite = New-Object System.Management.Automation.Host.ChoiceDescription "&Overwrite" $ChoiceCancel = New-Object System.Management.Automation.Host.ChoiceDescription "&Cancel" if($FileSize -lt (Get-Item -Path $LocalPath).Length) { $ChoiceResume = New-Object System.Management.Automation.Host.ChoiceDescription "&Resume" $Options = [System.Management.Automation.Host.ChoiceDescription[]]($ChoiceCancel, $ChoiceOverwrite, $ChoiceResume) $SendFlag = $host.ui.PromptForChoice($Title, $Message, $Options, 2) } else { $Options = [System.Management.Automation.Host.ChoiceDescription[]]($ChoiceCancel, $ChoiceOverwrite) $SendFlag = $host.ui.PromptForChoice($Title, $Message, $Options, 1) } } } if($SendFlag -eq 2) { $Request.Method = [System.Net.WebRequestMethods+FTP]::AppendFile } else { $Request.Method = [System.Net.WebRequestMethods+FTP]::UploadFile } Write-Debug "Use WebRequestMethods: $($Request.Method)" if($SendFlag) { $File = [IO.File]::OpenRead( (Convert-Path $LocalItem.Fullname) ) Write-Debug "Open File: $LocalPath" $Response = $Request.GetRequestStream() [Byte[]]$Buffer = New-Object Byte[] $BufferSize $ReadedData = 0 $AllReadedData = 0 $TotalData = (Get-Item $LocalPath).Length if($SendFlag -eq 2) { $SeekOrigin = [System.IO.SeekOrigin]::Begin $File.Seek($FileSize,$SeekOrigin) | Out-Null $AllReadedData = $FileSize } if($TotalData -eq 0) { $TotalData = 1 } Do { $ReadedData = $File.Read($Buffer, 0, $Buffer.Length) $AllReadedData += $ReadedData $Response.Write($Buffer, 0, $ReadedData); Write-Progress -Activity "Upload File: $Path/$ItemName" -Status "Uploading:" -Percentcomplete ([int]($AllReadedData/$TotalData * 100)) } While($ReadedData -gt 0) $File.Close() $Response.Close() Write-Debug "Close File: $LocalPath" Return Get-FTPChildItem -Path $RequestUri -Session $Session } } Catch { Write-Error $_.Exception.Message -ErrorAction Stop } } } } else { Write-Error "Cannot find local path '$LocalPath' because it does not exist." -ErrorAction Stop } } End { $CurrentSession.StartPath = "" } } |