0

I'm trying to use PowerShell to upload a (long) list of queued files, using System.Net.WebClient and the UploadFile function. This works fine, but after a file us uploaded, the ftp-connection never closes, either when the WebClient object instance goes out of scope or even after the script has finished. The function looks as follows:

function Upload-File() {
    Param (
        [string] $user,
        [string] $password,
        [string] $srceFileName,
        [string] $destFileName
    )
    # Set up FTP-client
    $client = New-Object System.Net.WebClient
    $client.Credentials = New-Object System.Net.NetworkCredential($user, $password)
    $client.UploadFile($destFileName, ".\$srceFileName")
    $client.Dispose()
}

All the information I can find states that the connection should close automatically when $client goes out of scope but this is clearly not happening.

Any idea on how to force the connection to close?

(This is part of a legacy system and for now I am stuck with ftp, so switching to another protocol is not an option.)

Dag Sondre Hansen
  • 2,449
  • 20
  • 22
  • 1
    Take a look at this [answer](https://stackoverflow.com/questions/16501845/webclient-is-opening-a-new-connection-each-time-i-download-a-file-and-all-of-the), it will answer your question. `Short answer: you shouldn't need to close the connections manually. They are managed for you behind the scenes.` – Otter Nov 14 '21 at 16:06
  • @Otter: the answer you refer to applies to C# not PowerShell. I am aware that connections eventually will be closed in the background, but waiting for a timeout to end the ftp-session is not an option, it simply takes way too long. – Dag Sondre Hansen Nov 14 '21 at 20:06
  • Powershell is built using .NET. The object you are creating is using a C# library - `System.Net.WebClient` ! – Otter Nov 15 '21 at 17:16

1 Answers1

1

For anyone else running into this problem, the solution is to use FtpWebRequest instead of WebClient and to set KeepAlive = $false. The function below will upload and then terminate the connection immediately afterwards.

function Upload-File() {
    Param (
        [string] $user,
        [string] $password,
        [string] $srceFileName,
        [string] $destFileName
    )
    $request = [Net.WebRequest]::Create($destFileName)
    $request.KeepAlive = $false
    $request.Credentials =
        New-Object System.Net.NetworkCredential($user, $password)
    $request.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile 
    
    $fileStream = [System.IO.File]::OpenRead(".\$srceFileName")
    $ftpStream = $request.GetRequestStream()
    $fileStream.CopyTo($ftpStream)
    
    $ftpStream.Dispose()
    $fileStream.Dispose()
}

This post pointed me in the right direction.

Dag Sondre Hansen
  • 2,449
  • 20
  • 22