More .NET components

Multiple files operations

These multi-file operations are compatible with a wide range of FTP servers. However, some FTP servers (mostly on mainframe systems) don't present a Unix-like filesystem and the methods described at this page are not compatible with those. On such servers, multi-file operations can still be implemented using a combination of GetList method and a single-file methods. See the following forum posts for an example: How to put multiple files to a mainframe and How to download FTP directory without using Download method.

Multi-file upload and download #

To transfer multiple files (such as all ".txt" files), use Upload and Download methods. Both take several arguments:

  • 1. Source path - path to a file or directory, or a mask (wildcard pattern)
  • 2. Target path - path to an existing directory
  • 3. Traversal mode (optional) - specifies how to transfer directories; if the source path is a mask, specifies how to search for files (default is recursive and shallow search)
  • 4. Transfer method (optional) - specifies whether to copy or move files
  • 5. Action on existing files (optional) - specifies what to do when a file already exists in target destination
Tip: To get more information about multi-file transfers and TraversalMode, see the Advanced Download and Upload blog post.

Uploading

CSharp

// upload a local file
ftp.Upload(@"C:\MyData\file.txt", "/MyData");

// upload all files from "MyData" directory only
// (files from subdirectories are not transferred)
ftp.Upload(@"C:\MyData\*", "/MyData", TraversalMode.MatchFilesShallow);

// upload all ".txt" files from "MyData" directory only
// (files from subdirectories are not transferred)
ftp.Upload(@"C:\MyData\*.txt", "/MyData", TraversalMode.MatchFilesShallow);

// upload all ".txt" files under "MyData" directory anywhere
// (files from subdirectories are transferred as well)
ftp.Upload(@"C:\MyData\*.txt", "/MyData", TraversalMode.MatchFilesDeep);

VisualBasic

' upload a local file
ftp.Upload("C:\MyData\file.txt", "/MyData")

' upload all files from "MyData" directory only
' (files from subdirectories are not transferred)
ftp.Upload("C:\MyData\*", "/MyData", TraversalMode.MatchFilesShallow)

' upload all ".txt" files from "MyData" directory only
' (files from subdirectories are not transferred)
ftp.Upload("C:\MyData\*.txt", "/MyData", TraversalMode.MatchFilesShallow)

' upload all ".txt" files under "MyData" directory anywhere
' (files from subdirectories are transferred as well)
ftp.Upload("C:\MyData\*.txt", "/MyData", TraversalMode.MatchFilesDeep)

Downloading

CSharp

// download a remote file
ftp.Download("/MyData/file.txt", @"C:\MyData");

// download all files from "/MyData" directory only
// (files from subdirectories are not transferred)
ftp.Download("/MyData/*", @"C:\MyData", TraversalMode.MatchFilesShallow);

// download all "*.txt" files from "/MyData" directory only
// (files from subdirectories are not transferred)
ftp.Download("/MyData/*.txt", @"C:\MyData", TraversalMode.MatchFilesShallow);

// download all "*.txt" files under "/MyData" directory anywhere
// (files from subdirectories are transferred as well)
ftp.Download("/MyData/*.txt", @"C:\MyData", TraversalMode.MatchFilesDeep);

VisualBasic

' download a remote file
ftp.Download("/MyData/file.txt", "C:\MyData")

' download all files from "/MyData" directory only
' (files from subdirectories are not transferred)
ftp.Download("/MyData/*", "C:\MyData", TraversalMode.MatchFilesShallow)

' download all "*.txt" files from "/MyData" directory only
' (files from subdirectories are not transferred)
ftp.Download("/MyData/*.txt", "C:\MyData", TraversalMode.MatchFilesShallow)

' download all "*.txt" files under "/MyData" directory anywhere
' (files from subdirectories are transferred as well)
ftp.Download("/MyData/*.txt", "C:\MyData", TraversalMode.MatchFilesDeep)

Recursive directory upload and download #

Upload and Download methods make it possible to easily transfer whole directories with all their content (with all the subfolders and files).

Tip: To get more information about recursive directory transfer, see the Basic Download and Upload blog post.

Uploading

CSharp

// upload the contents of a local directory
//  - upload goes into "/MyData"
//  - "/MyData/MyData" is not created at the server
ftp.Upload(@"C:\MyData\*", "/MyData");

// upload a whole local directory
//  - upload goes into "/MyData/Exports"
//  - "/MyData/Exports" is created at the server
ftp.Upload(@"C:\MyData\Exports", "/MyData");

VisualBasic

' upload the contents of a local directory
'  - upload goes into "/MyData"
'  - "/MyData/MyData" is not created at the server
ftp.Upload("C:\MyData\*", "/MyData")

' upload a whole local directory
'  - upload goes into "/MyData/Exports"
'  - "/MyData/Exports" is created at the server
ftp.Upload("C:\MyData\Exports", "/MyData")

Downloading

CSharp

// download content of a remote directory
//  - download goes into "C:\MyData"
//  - "C:\MyData\MyData" is not created at the client
ftp.Download("/MyData/*", @"C:\MyData");

// download a whole remote directory
//  - download goes into "C:\MyData\Exports"
//  - "C:\MyData\Exports" is created at the client
ftp.Download("/MyData/Exports", @"C:\MyData");

VisualBasic

' download content of a remote directory
'  - download goes into "C:\MyData"
'  - "C:\MyData\MyData" is not created at the client
ftp.Download("/MyData/*", "C:\MyData")

' download a whole remote directory
'  - download goes into "C:\MyData\Exports"
'  - "C:\MyData\Exports" is created at the client
ftp.Download("/MyData/Exports", "C:\MyData")

Deleting multiple files #

To delete multiple files (such as all ".tmp" files), use Delete method:

CSharp

// delete all files in "/MyData" directory only
// (keep files in subdirectories)
ftp.Delete("/MyData/*", TraversalMode.MatchFilesShallow);

// delete all ".tmp" files in "/MyData" directory only
// (keep ".tmp" files in subdirectories)
ftp.Delete("/MyData/*.tmp", TraversalMode.MatchFilesShallow);

// delete all ".tmp" files anywhere
// (delete ".tmp" files in subdirectories as well)
ftp.Delete("/MyData/*.tmp", TraversalMode.MatchFilesDeep);

VisualBasic

' delete all files in "/MyData" directory only
' (keep files in subdirectories)
ftp.Delete("/MyData/*", TraversalMode.MatchFilesShallow)

' delete all ".tmp" files in "/MyData" directory only
' (keep ".tmp" files in subdirectories)
ftp.Delete("/MyData/*.tmp", TraversalMode.MatchFilesShallow)

' delete all ".tmp" files anywhere
' (delete ".tmp" files in subdirectories as well)
ftp.Delete("/MyData/*.tmp", TraversalMode.MatchFilesDeep)

Deleting directories recursively #

Delete method makes it possible to delete whole directories (with all their content) as well:

CSharp

// only delete the contents of a remote directory
// (keep the directory itself)
ftp.Delete("/MyData/Temp/*", TraversalMode.Recursive);

// delete a remote directory with its whole content recursively
ftp.Delete("/MyData/Temp", TraversalMode.Recursive);

VisualBasic

' only delete the contents of a remote directory
' (keep the directory itself)
ftp.Delete("/MyData/Temp/*", TraversalMode.Recursive)

' delete a remote directory with its whole content recursively
ftp.Delete("/MyData/Temp", TraversalMode.Recursive)

Using wildcards #

Wildcards are used to specify multiple files or directories whose names match a pattern. Supported wildcards are:

  • asterisk ('*') - matches any number (0, 1 or more) of any characters except a directory separator ("a*b" matches "ab", "axb", "axyzb", but not "a/b" or "ax/yb")
  • question mark ('?') - matches exactly one character except a directory separator ("a?b" matches "axb" and "ayb", but not "ab", "axyzb" or "a/b")
Tip: Wildcard pattern matching mode can be tuned using the optional TraversalMode argument. For more information, see the Advanced Download and Upload blog post.

CSharp

// download all January ".csv" exports from 2000
ftp.Download("/MyData/Exports/2000-01-??.csv", @"C:\MyData");

// upload content of "C:\MyData" to "/MyData"
// (subdirectories are uploaded as well)
ftp.Upload(@"C:\MyData\*", "/MyData");

// upload all ".txt" files from "C:\MyData" only
// (files from subdirectories are not uploaded)
ftp.Upload(@"C:\MyData\*.txt", "/MyData", TraversalMode.MatchFilesShallow);

// upload all ".txt" files from "C:\MyData" and under
// (files from subdirectories are uploaded as well)
ftp.Upload(@"C:\MyData\*.txt", "/MyData", TraversalMode.MatchFilesDeep);

VisualBasic

' download all January ".csv" exports from 2000
ftp.Download("/MyData/Exports/2000-01-??.csv", "C:\MyData")

' upload content of "C:\MyData" to "/MyData"
' (subdirectories are uploaded as well)
ftp.Upload("C:\MyData\*", "/MyData")

' upload all ".txt" files from "C:\MyData" only
' (files from subdirectories are not uploaded)
ftp.Upload("C:\MyData\*.txt", "/MyData", TraversalMode.MatchFilesShallow)

' upload all ".txt" files from "C:\MyData" and under
' (files from subdirectories are uploaded as well)
ftp.Upload("C:\MyData\*.txt", "/MyData", TraversalMode.MatchFilesDeep)

Using FileSet #

When simple wildcard patters are not powerful enough, use Rebex.IO.FileSet object. It makes it possible to combine multiple matching criteria (such as all ".txt" and ".csv" files) and specify exclude criteria as well.

In addition to common wildcards and TraversalMode criteria, a special "**" wildcard is available that matches any character, including directory separators ("/MyData/**/file.txt" matches "/MyData/file.txt" and also "/MyData/a/b/c/file.txt").

CSharp

// prepare file set
var fileSet = new Rebex.IO.FileSet(@"C:\MyData");
// include some files - the path or mask is relative to the C:\MyData base path
fileSet.Include("*.txt", TraversalMode.MatchFilesShallow);
// include some directories
fileSet.Include("*Web*/");
// exclude ".tmp" files (in any location)
fileSet.Exclude("*.tmp", TraversalMode.MatchFilesDeep);
// exclude "Backups" directories (in any location)
fileSet.Exclude("**/Backups/");
// exclude "C:\MyData\Ignore" directory
fileSet.Exclude("Ignore");

// display all the files to be uploaded
Console.WriteLine("Uploading files:");
foreach (LocalItem item in fileSet.GetLocalItems())
{
    Console.WriteLine(item.FullPath);
}

// upload all files and directories matching the file set
ftp.Upload(fileSet, "/MyData");

VisualBasic

' prepare file set
Dim fileSet = New Rebex.IO.FileSet("C:\MyData")
' include some files
fileSet.Include("*.txt", TraversalMode.MatchFilesShallow)
' include some directories
fileSet.Include("*Web*/")
' exclude ".tmp" files (in any location)
fileSet.Exclude("*.tmp", TraversalMode.MatchFilesDeep)
' exclude "Backups" directories (in any location)
fileSet.Exclude("**/Backups/")

' display all the files to be uploaded
Console.WriteLine("Uploading files:")
For Each item As LocalItem In fileSet.GetLocalItems()
    Console.WriteLine(item.FullPath)
Next

' upload all files and directories matching the file set
ftp.Upload(fileSet, "/MyData")

Extending FileSet class

When wildcard patterns are still not powerful enough, you can easily extend the FileSet class and add custom matching code. Just inherit from Rebex.IO.FileSet and override the IsMatch method.

Tip: See our forum post for custom FileSet implementation which uses regular expression to filter files.

Merging multiple directories #

FileSet object can even be used to upload (or download) files from multiple directories (or even a whole directory tree) into a single directory - just set Rebex.IO.FileSet.Flatten to true and call the Upload or Download method.

For example, when uploading files "A\a.txt" and "B\b.txt" to "/MyData" directory, both the files end up in the "/MyData" directory (and no "A" or "B" directories are created).

CSharp

// prepare a file set
// (all files from "C:\MyData" and its subdirectories)
var fileSet = new Rebex.IO.FileSet(@"C:\MyData", "*");
fileSet.Flatten = true;

// upload the files
ftp.Upload(fileSet, "/MyData");

VisualBasic

' prepare a file set
' (all files from "C:\MyData" and its subdirectories)
Dim fileSet = New Rebex.IO.FileSet("C:\MyData", "*")
fileSet.Flatten = True

' upload the files
ftp.Upload(fileSet, "/MyData")

Moving files between client and server #

Upload and Download methods support move mode, in which files (and optionally directories) are deleted once successfully transferred - just specify TransferMethod.Move mode in the method call.

To further refine move behavior, set Settings.MultiFileMoveMode to:

  • MoveMode.All (default) - move both files and directories
  • MoveMode.FilesOnly - move files only (keep source directory structure)

CSharp

// this is the default mode (it's not necessary to set it)
ftp.Settings.MultiFileMoveMode = MoveMode.All;

// move whole directory "Exports" to the server
ftp.Upload(@"C:\MyData\Exports", "/MyData", 0, TransferMethod.Move, 0);

// set the option to only move files
ftp.Settings.MultiFileMoveMode = MoveMode.FilesOnly;

// move files from server to client
// (create directory structure at the client; keep it at the server as well)
ftp.Download("/MyData/*", @"C:\MyData", 0, TransferMethod.Move, 0);

VisualBasic

' this is the default mode (it's not necessary to set it)
ftp.Settings.MultiFileMoveMode = MoveMode.All

' move whole directory "Exports" to the server
ftp.Upload("C:\MyData\Exports", "/MyData", 0, TransferMethod.Move, 0)

' set the option to only move files
ftp.Settings.MultiFileMoveMode = MoveMode.FilesOnly

' move files from server to client
' (create directory structure at the client keep it at the server as well)
ftp.Download("/MyData/*", "C:\MyData", 0, TransferMethod.Move, 0)

Tip: To move files at the server (not between the client and a server), use Rename method instead.

Symlink detection and handling #

Upload and Download methods automatically detect symbolic links. To specify whether to resolve them, skip them or raise an error, set Settings.MultiFileLinkMode to:

  • FollowLinks - resolves links and processes them like other items
  • SkipLinks - skips links and continue processing
  • ThrowExceptionOnLinks - cancels processing by throwing an exception

CSharp

// don't process links
ftp.Settings.MultiFileLinkMode = LinkProcessingMode.SkipLinks;

// download directory without links
ftp.Download("test-links/*", @"C:\MyData");

VisualBasic

' don't process links
ftp.Settings.MultiFileLinkMode = LinkProcessingMode.SkipLinks

' download directory without links
ftp.Download("test-links/*", "C:\MyData")

Multi-file methods contain built-in infinite loop detection. When an infinite loop in the directory structure is detected, a ProblemDetected event is raised with ProblemDetectedEventArgs.ProblemType set to InfiniteLoopDetected.

Note: Symlinks detection is supported only by some FTP servers (usually not supported on servers like IIS).