More .NET components

More file transfer operations

Resuming interrupted transfers #

When a connection is lost or aborted, you may end up with incompletely transferred file. Instead of transferring in all over again, it's possible to resume the operation and only transfer the missing part.

Upload and Download methods can do this - just specify ActionOnExistingFiles.ResumeIfPossible when calling. This will:

  • transfer files which were not transferred yet (don't exist at the destination)
  • transfer remaining parts of files which are smaller at the destination than on source
  • skip all other files

CSharp

// auto-resume failed directory upload
sftp.Upload(@"C:\MyData\*", "/MyData",
    0, 0, ActionOnExistingFiles.ResumeIfPossible);

// auto-resume failed single file download
sftp.Download("/MyData/file.txt", @"C:\MyData",
    0, 0, ActionOnExistingFiles.ResumeIfPossible);

VisualBasic

' auto-resume failed directory upload
sftp.Upload("C:\MyData\*", "/MyData",
    0, 0, ActionOnExistingFiles.ResumeIfPossible)

' auto-resume failed single file download
sftp.Download("/MyData/file.txt", "C:\MyData",
    0, 0, ActionOnExistingFiles.ResumeIfPossible)
Note: Using ResumeIfPossible will not re-establish interrupted transfer automatically. If transfer is aborted, you have to re-establish connection and start transfer with ResumeIfPossible manually.

Overwriting existing files #

When transferring multiple files using Upload or Download method, use ActionOnExistingFiles argument to specify what to do when a target file already exists.

To overwrite existing files, use one of these options:

  • OverwriteAll - Overwrites all files.
  • OverwriteOlder - Overwrites files which are older that source files.
  • OverwriteDifferentSize - Overwrites files which have different size.

Alternatively, in order not to overwrite existing files, use one of these instead:

  • SkipAll - Skip files.
  • ResumeIfPossible - Resume the transfer if possible.
  • Rename - Rename files using "filename[number].extension" pattern.
  • ThrowException - Fail with an error.
Tip: The ActionOnExistingFiles argument specifies default behavior. However, you can still override it using ProblemDetected event.

CSharp

// set desired overwrite mode according to a .config file
ActionOnExistingFiles action = ActionOnExistingFiles.ThrowException;
switch (ConfigurationManager.AppSettings["OverwriteMode"])
{
    case "skip": action = ActionOnExistingFiles.SkipAll; break;
    case "all": action = ActionOnExistingFiles.OverwriteAll; break;
    case "older": action = ActionOnExistingFiles.OverwriteOlder; break;
    case "size": action = ActionOnExistingFiles.OverwriteDifferentSize; break;
}

// set granularity to whole days (ignore time component)
// used when OverwriteOlder is selected
sftp.Settings.TimeComparisonGranularity = TimeComparisonGranularity.Days;

// upload directory with specific overwrite mode
sftp.Upload(@"C:\MyData\*", "/MyData", 0, 0, action);

VisualBasic

' set desired overwrite mode according to a .config file
Dim action = ActionOnExistingFiles.ThrowException
Select Case ConfigurationManager.AppSettings("OverwriteMode")
    Case "skip" : action = ActionOnExistingFiles.SkipAll
    Case "all" : action = ActionOnExistingFiles.OverwriteAll
    Case "older" : action = ActionOnExistingFiles.OverwriteOlder
    Case "size" : action = ActionOnExistingFiles.OverwriteDifferentSize
End Select

' set granularity to whole days (ignore time component)
' used when OverwriteOlder is selected
sftp.Settings.TimeComparisonGranularity = TimeComparisonGranularity.Days

' upload directory with specific overwrite mode
sftp.Upload("C:\MyData\*", "/MyData", 0, 0, action)

Auto-renaming existing files #

When transferring multiple files using Upload or Download method, specify the ActionOnExistingFiles.Rename argument to automatically rename transferred file if the target file already exists. This will add a number between the filename and extension ("filename[number].extension" pattern).

Tip: To specify a different new name, use ProblemDetected event instead.

CSharp

// upload directory,
// auto-rename transferred files
// if target file already exists
sftp.Upload(@"C:\MyData\*", "/MyData",
    0, 0, ActionOnExistingFiles.Rename);

// download file,
// rename it if "C:\MyData\file.txt" already exists
// (e.g., "C:\MyData\file[1].txt" might be created)
sftp.Download("/MyData/file.txt", @"C:\MyData",
    0, 0, ActionOnExistingFiles.Rename);

VisualBasic

' upload directory,
' auto-rename transferred files
' if target file already exists
sftp.Upload("C:\MyData\*", "/MyData",
    0, 0, ActionOnExistingFiles.Rename)

' download file,
' rename it if "C:\MyData\file.txt" already exists
' (e.g., "C:\MyData\file[1].txt" might be created)
sftp.Download("/MyData/file.txt", "C:\MyData",
    0, 0, ActionOnExistingFiles.Rename)

Progress reporting #

Displaying progress of both single-file and multi-file transfers is simple with TransferProgressChanged event. It keeps you updated with:

  • ProgressPercentage - percentage of the whole operation that has been completed (useful when transferring multiple files)
  • CurrentFileProgressPercentage - percentage of the current file that has been transferred
  • BytesPerSecond - approximate current transfer speed
  • Action - current action (upload or download)
  • SourceItem - information about the currently processed item
  • TransferState - current operation state (processing file or directory, data block, whole file transferred, ...)
  • And much more (TargetPath, FilesProcessed, FilesTotal, ...)
Tip: To get informed about the progress of traversing directory hierarchy structure, use the Traversing event.

Sample transfer progress event handler:

CSharp

System.Windows.Forms.ProgressBar fileProgressBar;
System.Windows.Forms.ProgressBar totalProgressBar;
System.Windows.Forms.Label transferSpeedLabel;

void client_TransferProgressChanged(object sender, SftpTransferProgressChangedEventArgs e)
{
    // update ProgressBar of the current file
    fileProgressBar.Value = (int)e.CurrentFileProgressPercentage;

    // update ProgressBar of the whole transfer
    totalProgressBar.Value = (int)e.ProgressPercentage;

    // update transfer speed
    transferSpeedLabel.Text = e.BytesPerSecond.ToString();
}

VisualBasic

Dim fileProgressBar As System.Windows.Forms.ProgressBar
Dim totalProgressBar As System.Windows.Forms.ProgressBar
Dim transferSpeedLabel As System.Windows.Forms.Label

Sub client_TransferProgressChanged(ByVal sender As Object, ByVal e As SftpTransferProgressChangedEventArgs)
    ' update ProgressBar of the current file
    fileProgressBar.Value = e.CurrentFileProgressPercentage

    ' update ProgressBar of the whole transfer
    totalProgressBar.Value = e.ProgressPercentage

    ' update transfer speed
    transferSpeedLabel.Text = e.BytesPerSecond.ToString()
End Sub

Registering the event:

CSharp

// register TransferProgressChanged event handler which is raised
// when a significant action occurs
sftp.TransferProgressChanged += client_TransferProgressChanged;

// transfer files
// ...

VisualBasic

' register TransferProgressChanged event handler which is raised
' when a significant action occurs
AddHandler sftp.TransferProgressChanged, AddressOf client_TransferProgressChanged

' transfer files
' ...

Transfer problem handling #

When a problem occurs in Upload or Download method, your code can get notified about it using the ProblemDetected event and react accordingly. See TransferProblemType enum for a list of possible problems you can handle.

The SftpProblemDetectedEventArgs argument of the event makes it possible to determine what is going on and choose an appropriate reaction. These are some of the properties available:

  • Exception - an exception (if any) which will be raised if the problem is not handled
  • ProblemType - the kind of problem that has occurred
  • Action - current action (upload, download, ...)
  • Reaction - selected reaction (fail, skip, overwrite, ...)

Sample ProblemDetected event handler

The following code shows a ProblemDetected event handler that provides a custom 'FileExists' problem handling:

  • Already-existing ".txt" files are renamed
  • Other already-existing files are overwritten, but only if they are older than 7 days
  • All other problems will be handled using the default behavior (see below)

CSharp

void client_ProblemDetected(object sender, SftpProblemDetectedEventArgs e)
{
    // handle only existing files problem
    if (e.ProblemType != TransferProblemType.FileExists)
        return;

    // rename ".txt" files
    if (Path.GetExtension(e.LocalPath) == ".txt")
    {
        e.Rename();
        return;
    }

    // initialize source and target dates (use whole date granularity)
    DateTime source = e.LocalItem.LastWriteTime.Value.Date;
    DateTime target = e.RemoteItem.LastWriteTime.Value.Date;

    // overwrite files which are older than 7 days
    if (source > target && target < DateTime.Now.AddDays(-7))
    {
        e.Overwrite();
        return;
    }
}

VisualBasic

Sub client_ProblemDetected(ByVal sender As Object, ByVal e As SftpProblemDetectedEventArgs)
    ' handle only existing files problem
    If e.ProblemType <> TransferProblemType.FileExists Then Return

    ' rename ".txt" files
    If Path.GetExtension(e.LocalPath) = ".txt" Then
        e.Rename()
        Return
    End If

    ' initialize source and target dates (use whole date granularity)
    Dim source = e.LocalItem.LastWriteTime.Value.Date
    Dim target = e.RemoteItem.LastWriteTime.Value.Date

    ' overwrite files which are older than 7 days
    If source > target AndAlso target < DateTime.Now.AddDays(-7) Then
        e.Overwrite()
        Return
    End If
End Sub

Registering the event and setting the default behavior:

CSharp

// register ProblemDetected event handler which is raised
// when target file already exists (besides other things)
sftp.ProblemDetected += client_ProblemDetected;

// upload directory (skip existing files by default)
sftp.Upload(@"C:\MyData\*", "/MyData", 0, 0, ActionOnExistingFiles.SkipAll);

VisualBasic

' register ProblemDetected event handler which is raised
' when target file already exists (besides other things)
AddHandler sftp.ProblemDetected, AddressOf client_ProblemDetected

' upload directory (skip existing files by default)
sftp.Upload("C:\MyData\*", "/MyData", 0, 0, ActionOnExistingFiles.SkipAll)

Restoring date&time after transfer #

By default, file times (creation, last access or last write time) are not synchronized after a successful file transfer. Use Settings.RestoreDateTime property to enable file time synchronization.

CSharp

// set to restore last modified time
sftp.Settings.RestoreDateTime = ItemDateTimes.LastWriteTime;

// transfer files
// ...

VisualBasic

' set to restore last modified time
sftp.Settings.RestoreDateTime = ItemDateTimes.LastWriteTime

' transfer files
' ...

Please note that time granularity of SFTP server and local file system can differ. For example, many SFTP servers ignore the millisecond part of file date/time.

ASCII and binary transfer modes #

The default transfer mode is binary, which means data is transferred as is without any processing. However, when transferring text data between platforms which use different end-of-line sequences (Windows use <CR><LF> Unix uses <LF>), it's useful to have the sequences automatically converted by setting the transfer mode to ASCII.

Use TransferType property to specify the desired transfer type. Optionally, set ServerType property to specify the target OS type as well (autodetection is not perfect).

CSharp

// set server type to UNIX
sftp.ServerType = SftpServerType.Unix;

// set transfer type to ASCII
sftp.TransferType = SftpTransferType.Ascii;

// transfer files
// ...

VisualBasic

' set server type to UNIX
sftp.ServerType = SftpServerType.Unix

' set transfer type to ASCII
sftp.TransferType = SftpTransferType.Ascii

' transfer files
' ...