More .NET libraries
-
Rebex FTP
.NET FTP client
-
Rebex SSH Shell
.NET SSH Shell
-
Rebex Total Pack
All Rebex .NET libraries together
Back to feature list...
Single file operations
On this page:
- Single-file upload and download
- Stream-based upload and download
- Deleting a file
- Rename/move a file
- Atomic POSIX rename
- Checking file existence
- Getting file length
- Getting and setting file date/time
- Getting file checksums
- Working with file attributes
- Creating symlinks and hard links
- Resolving symlinks
- Partial file transfer (appending)
- Partial file transfer (resuming)
Single-file upload and download
Use PutFile
method to upload a single file, and GetFile
method to download it.
Both methods require a target name, which means it's possible to use a different target file name if needed.
// upload a local file to server sftp.PutFile(@"C:\MyData\file.txt", "/MyData/file.txt"); // download from server to a local file using a different name sftp.GetFile("/MyData/file.txt", @"C:\MyData\copy-file.txt");
' upload a local file to server sftp.PutFile("C:\MyData\file.txt", "/MyData/file.txt") ' download from server to a local file using a different name sftp.GetFile("/MyData/file.txt", "C:\MyData\copy-file.txt")
These methods overwrite any existing files. To check whether a remote file exists,
use FileExists
method.
Upload
and Download
methods. They accept single-file input as well and support both single-file and multi-file transfers.
Stream-based upload and download
Both PutFile
and GetFile
methods accept a System.IO.Stream
object, making it possible to
transfer data from/to any kind of stream.
For example, use MemoryStream
when processing data in memory, without having to create temporary disk files:
Upload from memory:
// prepare data byte[] data = System.Text.Encoding.UTF8.GetBytes("test data"); // convert data to a memory stream var stream = new MemoryStream(data); // upload data from memory sftp.PutFile(stream, "/MyData/file.txt");
' prepare data Dim data() As Byte = System.Text.Encoding.UTF8.GetBytes("test data") ' convert data to a memory stream Dim stream As New MemoryStream(data) ' upload data from memory sftp.PutFile(stream, "/MyData/file.txt")
Download to memory:
// download a remote file into a memory stream var stream = new MemoryStream(); sftp.GetFile("/MyData/file.txt", stream); // convert memory stream to data byte[] data = stream.ToArray();
' download a remote file into a memory stream Dim stream As New MemoryStream() sftp.GetFile("/MyData/file.txt", stream) ' convert memory stream to data Dim data() As Byte = stream.ToArray()
Tip: To access remote files directly using general System.IO.Stream
, use
Advanced stream-based API.
Deleting a file
To delete a remote file, use DeleteFile
method.
For example, to delete a remote file that doesn't exist locally, use the following code:
// if local file is deleted if (!File.Exists(@"C:\MyData\file.txt")) { // delete remote file as well sftp.DeleteFile("/MyData/file.txt"); }
' if local file is deleted If Not File.Exists("C:\MyData\file.txt") Then ' delete remote file as well sftp.DeleteFile("/MyData/file.txt") End If
Tip: For deleting multiple files or non-empty directories,
use Delete
method.
Rename/move a file
To rename a remote file or directory, use Rename
method.
It can also be used for moving a remote file or directory to another location on the file system of the remote host.
// rename a remote file sftp.Rename("/MyData/a.txt", "/MyData/b.txt"); // move a remote file sftp.Rename("/MyData/file.txt", "/Backups/file.txt");
' rename a remote file sftp.Rename("/MyData/a.txt", "/MyData/b.txt") ' move a remote file sftp.Rename("/MyData/file.txt", "/Backups/file.txt")
Tip: For moving files between client and server,
use Upload
or Download
methods with the TransferMethod.Move
argument specified.
Atomic POSIX rename
SFTP protocol's rename operation fails when the target file already exists. This poses a problem for Unix-like filesystems based on POSIX standard, which specifies that the target file is deleted if it already exists.
Because of this, Unix-based SFTP servers can't implement SFTP rename command using Unix's POSIX-like rename function, but have to work around the difference by creating a hard link using the new name, followed by removing the original name. Unfortunately, this approach fails on filesystems that don't support hard links (such as FAT).
Another problem with this approach is that SFTP rename is not atomic because it consists of two operations, unlike POSIX rename function.
To solve these issues, a 'posix-rename' extension was introduced in OpenSSH 4.8 and has been implemented by other SFTP
servers as well. To use this extension (when available), just set Sftp
object's Settings.UsePosixRename
property to true.
// use 'Posix rename' when available sftp.Settings.UsePosixRename = true; // rename a remote file sftp.Rename("/MyData/a.txt", "/MyData/b.txt");
' use 'Posix rename' when available sftp.Settings.UsePosixRename = True ' rename a remote file sftp.Rename("/MyData/a.txt", "/MyData/b.txt")
Checking file existence
To check whether a remote file already exists, use FileExists
method.
This is useful, for example, when you are about to upload a file, but would like to ask the user whether to overwrite an existing target file first:
// check whether a remote file exists bool exists = sftp.FileExists("/MyData/file.txt"); if (exists) { // prompt the user // ... }
' check whether a remote file exists Dim exists = sftp.FileExists("/MyData/file.txt") If exists Then ' prompt the user ' ... End If
Getting file length
To retrieve the length of a remote file, use GetFileLength
method:.
This can be used to determine the current remote file length when resuming a broken transfer or in order to ask the user for permission before downloading a large file over a slow network:
// get the length of a remote file long length = sftp.GetFileLength("/MyData/file.txt"); // large downloads need user permission if (length > 1024 * 1024) { // prompt the user what to do with file > 1 MB // ... }
' get the length of a remote file Dim length = sftp.GetFileLength("/MyData/file.txt") ' large downloads need user permission If length > 1024 * 1024 Then ' prompt the user what to do with file > 1 MB ' ... End If
Getting and setting file date/time
To retrieve the last modification date/time of a remote file, use GetFileDateTime
method. To set it, use SetFileDateTime
method.
Getting remote time
string localPath = @"C:\MyData\file.txt"; string remotePath = "/MyData/file.txt"; DateTime remoteTime = sftp.GetFileDateTime(remotePath); // download file and set local time appropriately sftp.GetFile(remotePath, localPath); File.SetLastWriteTime(localPath, remoteTime);
Dim localPath = "C:\MyData\file.txt" Dim remotePath = "/MyData/file.txt" Dim remoteTime = sftp.GetFileDateTime(remotePath) ' download file and set local time appropriately sftp.GetFile(remotePath, localPath) File.SetLastWriteTime(localPath, remoteTime)
Setting remote time
string localPath = @"C:\MyData\file.txt"; string remotePath = "/MyData/file.txt"; DateTime localTime = new FileInfo(localPath).LastWriteTime; // upload file and set remote time appropriately sftp.PutFile(localPath, remotePath); sftp.SetFileDateTime(remotePath, localTime);
Dim localPath = "C:\MyData\file.txt" Dim remotePath = "/MyData/file.txt" Dim localTime = New FileInfo(localPath).LastWriteTime ' upload file and set remote time appropriately sftp.PutFile(localPath, remotePath) sftp.SetFileDateTime(remotePath, localTime)
Getting file checksums
To make it possible to verify the file has been transferred correctly, some SFTP servers support checksum calculation (via the 'check-file' SFTP extension), making it possible to compare checksums of local and remote files.
string localPath = @"C:\MyData\file.txt"; string remotePath = "file.txt"; // upload the file sftp.PutFile(localPath, remotePath); // compute checksums var checksumAlgorithm = ChecksumAlgorithm.SHA256; string remoteChecksum = sftp.GetChecksum(remotePath, checksumAlgorithm); string localChecksum = LocalItem.GetChecksum(localPath, checksumAlgorithm); // compare checksums if (remoteChecksum == localChecksum) Console.WriteLine("File uploaded and verified."); else Console.WriteLine("File uploaded with errors.");
Dim localPath = "C:\MyData\file.txt" Dim remotePath = "file.txt" ' upload the file sftp.PutFile(localPath, remotePath) ' compute checksums Dim checksumAlgorithm As ChecksumAlgorithm = ChecksumAlgorithm.SHA256 Dim remoteChecksum As String = sftp.GetChecksum(remotePath, checksumAlgorithm) Dim localChecksum As String = LocalItem.GetChecksum(localPath, checksumAlgorithm) ' compare checksums If remoteChecksum = localChecksum Then Console.WriteLine("File uploaded and verified.") Else Console.WriteLine("File uploaded with errors.") End If
SSH has reliable built-in integrity checks, which mostly makes it unnecessary to verify transferred files using checksums.
Note: This functionality only works with servers that support the file-check
extension.
Working with file attributes
SFTP protocol makes it possible to retrieve or set several file and directory attributes:
- Last modification time
- Last access time
- Creation time
- Permissions
- Owner and group
These are accessible through properties of SftpItem
object, which can be retrieved by calling GetInfo
, GetList
or GetItems
methods.
To set these attributes, create an instance of SftpAttributes
object, set its properties and pass it to SetAttributes
method.
The following code snippet shows how to grant other users write access to a file:
// get the info about a remote file SftpItem item = sftp.GetInfo("/MyData/file.txt"); // prepare attributes (allow others to write as well) SftpAttributes attributes = new SftpAttributes(); attributes.Permissions = item.Permissions | SftpPermissions.OthersWrite; // set the file attributes sftp.SetAttributes("/MyData/file.txt", attributes);
' get the info about a remote file Dim item = sftp.GetInfo("/MyData/file.txt") ' prepare attributes (allow others to write as well) Dim attributes = New SftpAttributes() attributes.Permissions = item.Permissions Or SftpPermissions.OthersWrite ' set the file attributes sftp.SetAttributes("/MyData/file.txt", attributes)
Please note that not all SFTP servers support all the attributes.
Creating symlinks and hard links
To create a symbolic link (symlink) or
a hard link, use CreateLink
method:
// create a symlink sftp.CreateLink("symlink.txt", "/MyData/file.txt", LinkType.Symbolic); // create a hard link sftp.CreateLink("hardlink.txt", "/MyData/file.txt", LinkType.Hard);
' create a symlink sftp.CreateLink("symlink.txt", "/MyData/file.txt", LinkType.Symbolic) ' create a hard link sftp.CreateLink("hardlink.txt", "/MyData/file.txt", LinkType.Hard)
Resolving symlinks
To retrieve the target path of a symbolic link, use ResolveSymlink
method:
// get the symlink target's real path string realPath = sftp.ResolveSymlink("symlink.txt"); // display the target of the link to the user // ...
' get real path of the symbolic link Dim realPath = sftp.ResolveSymlink("/MyData/link.txt") ' display the target of the link to the user ' ...
Partial file transfer (appending)
GetFile
and PutFile
methods make it possible to download or upload a part of a file.
This is often used for appending data to an existing file, or to resume broken transfers.
Of course, it is possible to write/read data to/from any other position in a file as well.
To upload and download specific file part, use three additional parameters: local offset, remote offset and number of bytes you want to transfer. Local offset is not required for stream-based methods - data is read/written from/to the current stream position.
string localPath = @"C:\MyData\part7.txt"; string remotePath = "/MyData/summary.txt"; string header = string.Format("<FILE>: {0}\n", localPath); long localFileLength = new FileInfo(localPath).Length; long remoteFileLength = sftp.GetFileLength(remotePath); // append header for part7.txt to summary.txt from memory MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(header)); sftp.PutFile(ms, remotePath, remoteFileLength, // remote offset ms.Length); // number of bytes to upload // update remote length remoteFileLength += ms.Length; // append data from part7.txt to summary.txt sftp.PutFile(localPath, remotePath, 0, // local offset remoteFileLength, // remote offset localFileLength); // number of bytes to upload
Dim localPath = "C:\MyData\part7.txt" Dim remotePath = "/MyData/summary.txt" Dim header = String.Format("<FILE>: {0}" & vbLf, localPath) Dim localFileLength = New FileInfo(localPath).Length Dim remoteFileLength = sftp.GetFileLength(remotePath) ' append header for part7.txt to summary.txt from memory Dim ms = New MemoryStream(Encoding.UTF8.GetBytes(header)) sftp.PutFile(ms, remotePath, remoteFileLength, ms.Length) ' remote offset, number of bytes to upload ' update remote length remoteFileLength += ms.Length ' append data from part7.txt to summary.txt sftp.PutFile(localPath, remotePath, 0, remoteFileLength, localFileLength) ' local offset, remote offset, number of bytes to upload
Partial file transfer (resuming)
If you need to simply resume a failed file transfer, use Upload and Download methods.
But if you prefer to have more control over the process, partial file transfer support
in GetFile
and PutFile
methods might be useful.
To resume a file transfer, determine the length of the local file and
the length of the remote file.
Then transfer the missing part.
Resuming upload:
string localPath = @"C:\MyData\file.txt"; string remotePath = "/MyData/file.txt"; long localFileLength = new FileInfo(localPath).Length; long remoteFileLength = sftp.GetFileLength(remotePath); long remains; // resume failed upload remains = localFileLength - remoteFileLength; if (remains > 0) { sftp.PutFile(localPath, remotePath, remoteFileLength, // local offset remoteFileLength, // remote offset remains); // number of bytes to upload }
Dim localPath = "C:\MyData\file.txt" Dim remotePath = "/MyData/file.txt" Dim localFileLength = New FileInfo(localPath).Length Dim remoteFileLength = sftp.GetFileLength(remotePath) Dim remains As Long ' resume failed upload remains = localFileLength - remoteFileLength If remains > 0 Then sftp.PutFile(localPath, remotePath, remoteFileLength, remoteFileLength, remains) ' local offset, remote offset, number of bytes to upload End If
Resuming download:
string localPath = @"C:\MyData\file.txt"; string remotePath = "/MyData/file.txt"; long localFileLength = new FileInfo(localPath).Length; long remoteFileLength = sftp.GetFileLength(remotePath); long remains; // resume failed download remains = remoteFileLength - localFileLength; if (remains > 0) { sftp.GetFile(remotePath, localPath, localFileLength, // remote offset localFileLength, // local offset remains); // number of bytes to download }
Dim localPath = "C:\MyData\file.txt" Dim remotePath = "/MyData/file.txt" Dim localFileLength = New FileInfo(localPath).Length Dim remoteFileLength = sftp.GetFileLength(remotePath) Dim remains As Long ' resume failed download remains = remoteFileLength - localFileLength If remains > 0 Then sftp.GetFile(remotePath, localPath, localFileLength, localFileLength, remains) ' remote offset, local offset, number of bytes to download End If
Back to feature list...