Search code examples
powershellfile-uploadftpwinscpwinscp-net

Batch file upload with WinSCP .NET assembly stops, when a single file upload fails


I'm using WinSCPto connect to a FTP and upload a bunch of files but I run into issues when a file fails to upload, when it happens the script stops, and the following files don't get uploaded. I'm mostly using the code from WinSCP's documentation

# Conectar
$session.Open($sessionOptions)

#Upload files
$transferResult = $session.PutFiles($origenSubida, $destinoSubida)

# Resultados de cada archivo
foreach ($transfer in $transferResult.Transfers)
{
    #looks if upload is correct
    if ($transfer.Error -eq $Null)
    {
        LogWrite ("$(Get-Date) upload complete {0} , changing folder" -f $transfer.FileName) 
        Move-Item $transfer.FileName $rutaArchivos
    }
    else
    {
        LogWrite ("$(Get-Date) Upload of {0} has failed: {1}" -f $transfer.Filename, $transfer.Error.Message)
    }
}

The unexpected behabior is the following:

I have 4 files in the folder that get uploaded, file 1, 2, 3 and 4, if I remove all permissions from file 3 and run the script, file 1 and 2 get uploaded to the FTP and they are moved to another directory, then the script ends with the error of no permission for file 3, file 4 does not get uploaded.

I'm not sure if I am overlooking anything, shouldn't the script continue even if it can't do anything with file3? I'm not sure if there's another way to make the upload of a single file to fail.


Solution

  • If you want a custom error handling, can loop the files on your own.

    $localPath = "C:\local\path"
    $remotePath = "/remote/path/"
    
    $localFiles = Get-ChildItem -Path $localPath
    
    foreach ($localFile in $localFiles)
    {
        Write-Host "Uploading $($localFile.FullName)..."
        $sourcePath = [WinSCP.RemotePath]::EscapeFileMask($localFile.FullName)
        $transferResult = $session.PutFiles($sourcePath, $remotePath)
    
        if (!$transferResult.IsSuccess)
        {
            # Print error (but continue with other files)
            Write-Host ("Error upload file $($localFile.FullName): " +
                "$($transferResult.Failures[0].Message)")
        }    
    }
    

    Another option is to handle the Session.QueryReceived event.


    Both options are covered in details in:
    Recursively download directory tree with custom error handling