using System; using System.Linq; using System.Collections.Generic; using System.IO; using Renci.SshNet.Sftp; using System.Text; using Renci.SshNet.Common; using System.Globalization; namespace Renci.SshNet { /// /// /// public partial class SftpClient : BaseClient { /// /// Holds SftpSession instance that used to communicate to the SFTP server /// private SftpSession _sftpSession; /// /// Gets or sets the operation timeout. /// /// The operation timeout. public TimeSpan OperationTimeout { get; set; } /// /// Gets or sets the size of the buffer. /// /// The size of the buffer. public uint BufferSize { get; set; } /// /// Gets remote working directory. /// public string WorkingDirectory { get { if (this._sftpSession == null) return null; return this._sftpSession.WorkingDirectory; } } /// /// Gets sftp protocol version. /// public int ProtocolVersion { get; private set; } #region Constructors /// /// Initializes a new instance of the class. /// /// The connection info. public SftpClient(ConnectionInfo connectionInfo) : base(connectionInfo) { this.OperationTimeout = new TimeSpan(0, 0, 0, 0, -1); this.BufferSize = 1024 * 32 - 38; } /// /// Initializes a new instance of the class. /// /// Connection host. /// Connection port. /// Authentication username. /// Authentication password. public SftpClient(string host, int port, string username, string password) : this(new PasswordConnectionInfo(host, port, username, password)) { } /// /// Initializes a new instance of the class. /// /// Connection host. /// Authentication username. /// Authentication password. public SftpClient(string host, string username, string password) : this(host, 22, username, password) { } /// /// Initializes a new instance of the class. /// /// Connection host. /// Connection port. /// Authentication username. /// Authentication private key file(s) . public SftpClient(string host, int port, string username, params PrivateKeyFile[] keyFiles) : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles)) { } /// /// Initializes a new instance of the class. /// /// Connection host. /// Authentication username. /// Authentication private key file(s) . public SftpClient(string host, string username, params PrivateKeyFile[] keyFiles) : this(host, 22, username, keyFiles) { } #endregion /// /// Changes remote directory to path. /// /// New directory path. public void ChangeDirectory(string path) { if (path == null) throw new ArgumentNullException("path"); // Ensure that connection is established. this.EnsureConnection(); this._sftpSession.ChangeDirectory(path); } /// /// Changes permissions of file(s) to specified mode. /// /// File(s) path, may match multiple files. /// The mode. public void ChangePermissions(string path, short mode) { if (path == null) throw new ArgumentNullException("path"); // Ensure that connection is established. this.EnsureConnection(); var file = this.Get(path); file.SetPermissions(mode); } /// /// Creates remote directory specified by path. /// /// Directory path to create. /// /// public void CreateDirectory(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(path); // Ensure that connection is established. this.EnsureConnection(); var fullPath = this._sftpSession.GetCanonicalPath(path); this._sftpSession.RequestMkDir(fullPath); } /// /// Deletes remote directory specified by path. /// /// Directory to be deleted path. public void DeleteDirectory(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); // Ensure that connection is established. this.EnsureConnection(); var fullPath = this._sftpSession.GetCanonicalPath(path); this._sftpSession.RequestRmDir(fullPath); } /// /// Deletes remote file specified by path. /// /// File to be deleted path. public void DeleteFile(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); // Ensure that connection is established. this.EnsureConnection(); var fullPath = this._sftpSession.GetCanonicalPath(path); this._sftpSession.RequestRemove(fullPath); } /// /// Renames remote file from old path to new path. /// /// Path to the old file location. /// Path to the new file location. public void RenameFile(string oldPath, string newPath) { if (oldPath == null) throw new ArgumentNullException("oldPath"); if (newPath == null) throw new ArgumentNullException("newPath"); // Ensure that connection is established. this.EnsureConnection(); var oldFullPath = this._sftpSession.GetCanonicalPath(oldPath); var newFullPath = this._sftpSession.GetCanonicalPath(newPath); this._sftpSession.RequestRename(oldFullPath, newFullPath); } /// /// Creates a symbolic link from old path to new path. /// /// The old path. /// The new path. public void SymbolicLink(string path, string linkPath) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); if (string.IsNullOrWhiteSpace(linkPath)) throw new ArgumentException("linkPath"); // Ensure that connection is established. this.EnsureConnection(); var fullPath = this._sftpSession.GetCanonicalPath(path); var linkFullPath = this._sftpSession.GetCanonicalPath(linkPath); this._sftpSession.RequestSymLink(fullPath, linkFullPath); } /// /// Retrieves list of files in remote directory. /// /// The path. /// List of directory entries public IEnumerable ListDirectory(string path) { return InternalListDirectory(path, null); } /// /// Begins an asynchronous operation of retrieving list of files in remote directory. /// /// The path. /// The method to be called when the asynchronous write operation is completed. /// A user-provided object that distinguishes this particular asynchronous write request from other requests. /// /// An that references the asynchronous operation. /// public IAsyncResult BeginListDirectory(string path, AsyncCallback asyncCallback, object state) { var asyncResult = new SftpListDirectoryAsyncResult(asyncCallback, state); this.ExecuteThread(() => { try { var result = this.InternalListDirectory(path, asyncResult); asyncResult.SetAsCompleted(result, false); } catch (Exception exp) { asyncResult.SetAsCompleted(exp, false); } }); return asyncResult; } /// /// Ends an asynchronous operation of retrieving list of files in remote directory. /// /// The pending asynchronous SFTP request. /// /// List of files /// public IEnumerable EndListDirectory(IAsyncResult asyncResult) { var ar = asyncResult as SftpListDirectoryAsyncResult; if (ar == null || ar.EndInvokeCalled) throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); // Wait for operation to complete, then return result or throw exception return ar.EndInvoke(); } /// /// Gets reference to remote file or directory. /// /// The path. /// public SftpFile Get(string path) { if (path == null) throw new ArgumentNullException("path"); var fullPath = this._sftpSession.GetCanonicalPath(path); var attributes = this._sftpSession.RequestLStat(fullPath); return new SftpFile(this._sftpSession, fullPath, attributes); } /// /// Checks whether file pr directory exists; /// /// The path. /// true if directory or file exists; otherwise false. public bool Exists(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); // Ensure that connection is established. this.EnsureConnection(); var fullPath = this._sftpSession.GetCanonicalPath(path); // Try to open as a file var handle = this._sftpSession.RequestOpen(fullPath, Flags.Read, true); if (handle == null) { handle = this._sftpSession.RequestOpenDir(fullPath, true); } if (handle == null) { return false; } else { this._sftpSession.RequestClose(handle); return true; } } /// /// Downloads remote file specified by the path into the stream. /// /// File to download. /// Stream to write the file into. public void DownloadFile(string path, Stream output) { this.InternalDownloadFile(path, output, null); } /// /// Begins an asynchronous file downloading into the stream. /// /// The path. /// The output. /// The method to be called when the asynchronous write operation is completed. /// A user-provided object that distinguishes this particular asynchronous write request from other requests. /// An that references the asynchronous operation. public IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback asyncCallback, object state) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); if (output == null) throw new ArgumentNullException("output"); // Ensure that connection is established. this.EnsureConnection(); var asyncResult = new SftpDownloadAsyncResult(asyncCallback, state); this.ExecuteThread(() => { try { this.InternalDownloadFile(path, output, asyncResult); asyncResult.SetAsCompleted(null, false); } catch (Exception exp) { asyncResult.SetAsCompleted(exp, false); } }); return asyncResult; } /// /// Ends an asynchronous file downloading into the stream. /// /// The pending asynchronous SFTP request. public void EndDownloadFile(IAsyncResult asyncResult) { var ar = asyncResult as SftpDownloadAsyncResult; if (ar == null || ar.EndInvokeCalled) throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); // Wait for operation to complete, then return result or throw exception ar.EndInvoke(); } /// /// Uploads stream into remote file.. /// /// Data input stream. /// Remote file path. public void UploadFile(Stream input, string path) { this.InternalUploadFile(input, path, null); } /// /// Begins an asynchronous uploading the steam into remote file. /// /// Data input stream. /// Remote file path. /// The method to be called when the asynchronous write operation is completed. /// A user-provided object that distinguishes this particular asynchronous write request from other requests. /// An that references the asynchronous operation. public IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback asyncCallback, object state) { if (input == null) throw new ArgumentNullException("input"); if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); // Ensure that connection is established. this.EnsureConnection(); var asyncResult = new SftpUploadAsyncResult(asyncCallback, state); this.ExecuteThread(() => { try { this.InternalUploadFile(input, path, asyncResult); asyncResult.SetAsCompleted(null, false); } catch (Exception exp) { asyncResult.SetAsCompleted(exp, false); } }); return asyncResult; } /// /// Ends an asynchronous uploading the steam into remote file. /// /// The pending asynchronous SFTP request. public void EndUploadFile(IAsyncResult asyncResult) { var ar = asyncResult as SftpUploadAsyncResult; if (ar == null || ar.EndInvokeCalled) throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); // Wait for operation to complete, then return result or throw exception ar.EndInvoke(); } #region File Methods /// /// Appends lines to a file, and then closes the file. /// /// The file to append the lines to. The file is created if it does not already exist. /// The lines to append to the file. public void AppendAllLines(string path, IEnumerable contents) { using (var stream = this.AppendText(path)) { foreach (var line in contents) { stream.WriteLine(line); } } } /// /// Appends lines to a file by using a specified encoding, and then closes the file. /// /// The file to append the lines to. The file is created if it does not already exist. /// The lines to append to the file. /// The character encoding to use. public void AppendAllLines(string path, IEnumerable contents, Encoding encoding) { using (var stream = this.AppendText(path, encoding)) { foreach (var line in contents) { stream.WriteLine(line); } } } /// /// Opens a file, appends the specified string to the file, and then closes the file. /// If the file does not exist, this method creates a file, writes the specified string to the file, then closes the file. /// /// The file to append the specified string to. /// The string to append to the file. public void AppendAllText(string path, string contents) { using (var stream = this.AppendText(path)) { stream.Write(contents); } } /// /// Opens a file, appends the specified string to the file, and then closes the file. /// If the file does not exist, this method creates a file, writes the specified string to the file, then closes the file. /// /// The file to append the specified string to. /// The string to append to the file. /// The character encoding to use. public void AppendAllText(string path, string contents, Encoding encoding) { using (var stream = this.AppendText(path, encoding)) { stream.Write(contents); } } /// /// Creates a that appends UTF-8 encoded text to an existing file. /// /// The path to the file to append to. /// A StreamWriter that appends UTF-8 encoded text to an existing file. public StreamWriter AppendText(string path) { return this.AppendText(path, Encoding.UTF8); } /// /// Creates a that appends UTF-8 encoded text to an existing file. /// /// The path to the file to append to. /// The character encoding to use. /// /// A StreamWriter that appends UTF-8 encoded text to an existing file. /// public StreamWriter AppendText(string path, Encoding encoding) { return new StreamWriter(new SftpFileStream(this._sftpSession, path, FileMode.Append, FileAccess.Write), encoding); } /// /// Creates or overwrites a file in the specified path. /// /// The path and name of the file to create. /// A that provides read/write access to the file specified in path public SftpFileStream Create(string path) { return new SftpFileStream(this._sftpSession, path, FileMode.Create, FileAccess.ReadWrite); } /// /// Creates or overwrites the specified file. /// /// The path and name of the file to create. /// The number of bytes buffered for reads and writes to the file. /// A that provides read/write access to the file specified in path public SftpFileStream Create(string path, int bufferSize) { return new SftpFileStream(this._sftpSession, path, FileMode.Create, FileAccess.ReadWrite, bufferSize); } /// /// Creates or opens a file for writing UTF-8 encoded text. /// /// The file to be opened for writing. /// A that writes to the specified file using UTF-8 encoding. public StreamWriter CreateText(string path) { return new StreamWriter(this.OpenWrite(path), Encoding.UTF8); } /// /// Creates or opens a file for writing UTF-8 encoded text. /// /// The file to be opened for writing. /// The character encoding to use. /// A that writes to the specified file using UTF-8 encoding. public StreamWriter CreateText(string path, Encoding encoding) { return new StreamWriter(this.OpenWrite(path), encoding); } /// /// Deletes the specified file or directory. An exception is not thrown if the specified file does not exist. /// /// The name of the file or directory to be deleted. Wildcard characters are not supported. public void Delete(string path) { var file = this.Get(path); if (file == null) { throw new SftpPathNotFoundException(path); } file.Delete(); } /// /// Returns the date and time the specified file or directory was last accessed. /// /// The file or directory for which to obtain access date and time information. /// A structure set to the date and time that the specified file or directory was last accessed. This value is expressed in local time. public DateTime GetLastAccessTime(string path) { var file = this.Get(path); return file.LastAccessTime; } /// /// Returns the date and time, in coordinated universal time (UTC), that the specified file or directory was last accessed. /// /// The file or directory for which to obtain access date and time information. /// A structure set to the date and time that the specified file or directory was last accessed. This value is expressed in UTC time. public DateTime GetLastAccessTimeUtc(string path) { var file = this.Get(path); return file.LastAccessTime.ToUniversalTime(); } /// /// Returns the date and time the specified file or directory was last written to. /// /// The file or directory for which to obtain write date and time information. /// A structure set to the date and time that the specified file or directory was last written to. This value is expressed in local time. public DateTime GetLastWriteTime(string path) { var file = this.Get(path); return file.LastWriteTime; } /// /// Returns the date and time, in coordinated universal time (UTC), that the specified file or directory was last written to. /// /// The file or directory for which to obtain write date and time information. /// A structure set to the date and time that the specified file or directory was last written to. This value is expressed in UTC time. public DateTime GetLastWriteTimeUtc(string path) { var file = this.Get(path); return file.LastWriteTime.ToUniversalTime(); } /// /// Opens a on the specified path with read/write access. /// /// The file to open. /// A value that specifies whether a file is created if one does not exist, and determines whether the contents of existing files are retained or overwritten. /// An unshared that provides access to the specified file, with the specified mode and access. public SftpFileStream Open(string path, FileMode mode) { return new SftpFileStream(this._sftpSession, path, mode, FileAccess.ReadWrite); } /// /// Opens a on the specified path, with the specified mode and access. /// /// The file to open. /// A value that specifies whether a file is created if one does not exist, and determines whether the contents of existing files are retained or overwritten. /// A value that specifies the operations that can be performed on the file. /// An unshared that provides access to the specified file, with the specified mode and access. public SftpFileStream Open(string path, FileMode mode, FileAccess access) { return new SftpFileStream(this._sftpSession, path, mode, access); } /// /// Opens an existing file for reading. /// /// The file to be opened for reading. /// A read-only System.IO.FileStream on the specified path. public SftpFileStream OpenRead(string path) { return new SftpFileStream(this._sftpSession, path, FileMode.Open, FileAccess.Read); } /// /// Opens an existing UTF-8 encoded text file for reading. /// /// The file to be opened for reading. /// A on the specified path. public StreamReader OpenText(string path) { return new StreamReader(this.OpenRead(path), Encoding.UTF8); } /// /// Opens an existing file for writing. /// /// The file to be opened for writing. /// An unshared object on the specified path with access. public SftpFileStream OpenWrite(string path) { return new SftpFileStream(this._sftpSession, path, FileMode.OpenOrCreate, FileAccess.Write); } /// /// Opens a binary file, reads the contents of the file into a byte array, and then closes the file. /// /// The file to open for reading. /// A byte array containing the contents of the file. public byte[] ReadAllBytes(string path) { using (var stream = this.OpenRead(path)) { var buffer = new byte[stream.Length]; stream.Read(buffer, 0, buffer.Length); return buffer; } } /// /// Opens a text file, reads all lines of the file, and then closes the file. /// /// The file to open for reading. /// A string array containing all lines of the file. public string[] ReadAllLines(string path) { return this.ReadAllLines(path, Encoding.UTF8); } /// /// Opens a file, reads all lines of the file with the specified encoding, and then closes the file. /// /// The file to open for reading. /// The encoding applied to the contents of the file. /// A string array containing all lines of the file. public string[] ReadAllLines(string path, Encoding encoding) { var lines = new List(); using (var stream = new StreamReader(this.OpenRead(path), encoding)) { while (!stream.EndOfStream) { lines.Add(stream.ReadLine()); } } return lines.ToArray(); } /// /// Opens a text file, reads all lines of the file, and then closes the file. /// /// The file to open for reading. /// A string containing all lines of the file. public string ReadAllText(string path) { return this.ReadAllText(path, Encoding.UTF8); } /// /// Opens a file, reads all lines of the file with the specified encoding, and then closes the file. /// /// The file to open for reading. /// The encoding applied to the contents of the file. /// A string containing all lines of the file. public string ReadAllText(string path, Encoding encoding) { var lines = new List(); using (var stream = new StreamReader(this.OpenRead(path), encoding)) { return stream.ReadToEnd(); } } /// /// Reads the lines of a file. /// /// The file to read. /// The lines of the file. public IEnumerable ReadLines(string path) { return this.ReadAllLines(path); } /// /// Read the lines of a file that has a specified encoding. /// /// The file to read. /// The encoding that is applied to the contents of the file. /// The lines of the file. public IEnumerable ReadLines(string path, Encoding encoding) { return this.ReadAllLines(path, encoding); } /// /// Sets the date and time the specified file was last accessed. /// /// The file for which to set the access date and time information. /// A containing the value to set for the last access date and time of path. This value is expressed in local time. public void SetLastAccessTime(string path, DateTime lastAccessTime) { throw new NotImplementedException(); } /// /// Sets the date and time, in coordinated universal time (UTC), that the specified file was last accessed. /// /// The file for which to set the access date and time information. /// A containing the value to set for the last access date and time of path. This value is expressed in UTC time. public void SetLastAccessTimeUtc(string path, DateTime lastAccessTimeUtc) { throw new NotImplementedException(); } /// /// Sets the date and time that the specified file was last written to. /// /// The file for which to set the date and time information. /// A System.DateTime containing the value to set for the last write date and time of path. This value is expressed in local time. public void SetLastWriteTime(string path, DateTime lastWriteTime) { throw new NotImplementedException(); } /// /// Sets the date and time, in coordinated universal time (UTC), that the specified file was last written to. /// /// The file for which to set the date and time information. /// A System.DateTime containing the value to set for the last write date and time of path. This value is expressed in UTC time. public void SetLastWriteTimeUtc(string path, DateTime lastWriteTimeUtc) { throw new NotImplementedException(); } /// /// Creates a new file, writes the specified byte array to the file, and then closes the file. If the target file already exists, it is overwritten. /// /// The file to write to. /// The bytes to write to the file. public void WriteAllBytes(string path, byte[] bytes) { using (var stream = this.OpenWrite(path)) { stream.Write(bytes, 0, bytes.Length); } } /// /// Creates a new file, writes a collection of strings to the file, and then closes the file. /// /// The file to write to. /// The lines to write to the file. public void WriteAllLines(string path, IEnumerable contents) { this.WriteAllLines(path, contents, Encoding.UTF8); } /// /// Creates a new file, write the specified string array to the file, and then closes the file. /// /// The file to write to. /// The string array to write to the file. public void WriteAllLines(string path, string[] contents) { this.WriteAllLines(path, contents, Encoding.UTF8); } /// /// Creates a new file by using the specified encoding, writes a collection of strings to the file, and then closes the file. /// /// The file to write to. /// The lines to write to the file. /// The character encoding to use. public void WriteAllLines(string path, IEnumerable contents, Encoding encoding) { using (var stream = this.CreateText(path, encoding)) { foreach (var line in contents) { stream.WriteLine(line); } } } /// /// Creates a new file, writes the specified string array to the file by using the specified encoding, and then closes the file. /// /// The file to write to. /// The string array to write to the file. /// An object that represents the character encoding applied to the string array. public void WriteAllLines(string path, string[] contents, Encoding encoding) { using (var stream = this.CreateText(path, encoding)) { foreach (var line in contents) { stream.WriteLine(line); } } } /// /// Creates a new file, writes the specified string to the file, and then closes the file. If the target file already exists, it is overwritten. /// /// The file to write to. /// The string to write to the file. public void WriteAllText(string path, string contents) { using (var stream = this.CreateText(path)) { stream.Write(contents); } } /// /// Creates a new file, writes the specified string to the file using the specified encoding, and then closes the file. If the target file already exists, it is overwritten. /// /// The file to write to. /// The string to write to the file. /// The encoding to apply to the string. public void WriteAllText(string path, string contents, Encoding encoding) { using (var stream = this.CreateText(path, encoding)) { stream.Write(contents); } } /// /// Gets the of the file on the path. /// /// The path to the file. /// The of the file on the path. public SftpFileAttributes GetAttributes(string path) { var fullPath = this._sftpSession.GetCanonicalPath(path); return this._sftpSession.RequestLStat(fullPath); } /// /// Sets the specified of the file on the specified path. /// /// The path to the file. /// The desired . public void SetAttributes(string path, SftpFileAttributes fileAttributes) { var fullPath = this._sftpSession.GetCanonicalPath(path); this._sftpSession.RequestSetStat(fullPath, fileAttributes); } //public FileSecurity GetAccessControl(string path); //public FileSecurity GetAccessControl(string path, AccessControlSections includeSections); //public DateTime GetCreationTime(string path); //public DateTime GetCreationTimeUtc(string path); //public void SetAccessControl(string path, FileSecurity fileSecurity); //public void SetCreationTime(string path, DateTime creationTime); //public void SetCreationTimeUtc(string path, DateTime creationTimeUtc); #endregion private IEnumerable InternalListDirectory(string path, SftpListDirectoryAsyncResult asynchResult) { if (path == null) throw new ArgumentNullException("path"); // Ensure that connection is established. this.EnsureConnection(); var fullPath = this._sftpSession.GetCanonicalPath(path); var handle = this._sftpSession.RequestOpenDir(fullPath); var basePath = fullPath; if (!basePath.EndsWith("/")) basePath = string.Format("{0}/", fullPath); var result = new List(); var files = this._sftpSession.RequestReadDir(handle); while (files != null) { result.AddRange(from f in files select new SftpFile(this._sftpSession, string.Format(CultureInfo.InvariantCulture, "{0}{1}", basePath, f.Key), f.Value)); if (asynchResult != null) { asynchResult.Update(result.Count); } files = this._sftpSession.RequestReadDir(handle); } return result; } private void InternalDownloadFile(string path, Stream output, SftpDownloadAsyncResult asynchResult) { if (output == null) throw new ArgumentNullException("output"); if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); // Ensure that connection is established. this.EnsureConnection(); var fullPath = this._sftpSession.GetCanonicalPath(path); var handle = this._sftpSession.RequestOpen(fullPath, Flags.Read); ulong offset = 0; var data = this._sftpSession.RequestRead(handle, offset, this.BufferSize); // Read data while available while (data != null) { output.Write(data, 0, data.Length); output.Flush(); offset += (ulong)data.Length; // Call callback to report number of bytes read if (asynchResult != null) { asynchResult.Update(offset); } data = this._sftpSession.RequestRead(handle, offset, this.BufferSize); } this._sftpSession.RequestClose(handle); } private void InternalUploadFile(Stream input, string path, SftpUploadAsyncResult asynchResult) { if (input == null) throw new ArgumentNullException("input"); if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); // Ensure that connection is established. this.EnsureConnection(); var fullPath = this._sftpSession.GetCanonicalPath(path); var handle = this._sftpSession.RequestOpen(fullPath, Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate); ulong offset = 0; var buffer = new byte[this.BufferSize]; var uploadCompleted = false; do { var bytesRead = input.Read(buffer, 0, buffer.Length); if (bytesRead < this.BufferSize) { var data = new byte[bytesRead]; Array.Copy(buffer, data, bytesRead); this._sftpSession.RequestWrite(handle, offset, data); uploadCompleted = true; } else { this._sftpSession.RequestWrite(handle, offset, buffer); } offset += (uint)bytesRead; // Call callback to report number of bytes read if (asynchResult != null) { asynchResult.Update(offset); } } while (!uploadCompleted); this._sftpSession.RequestClose(handle); } partial void ExecuteThread(Action action); /// /// Called when client is connected to the server. /// protected override void OnConnected() { base.OnConnected(); this._sftpSession = new SftpSession(this.Session, this.OperationTimeout); this._sftpSession.Connect(); // Resolve current running version this.ProtocolVersion = this._sftpSession.ProtocolVersion; } /// /// Called when client is disconnecting from the server. /// protected override void OnDisconnecting() { base.OnDisconnecting(); this._sftpSession.Disconnect(); } /// /// Releases unmanaged and - optionally - managed resources /// /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages. protected override void Dispose(bool disposing) { if (this._sftpSession != null) { this._sftpSession.Dispose(); this._sftpSession = null; } base.Dispose(disposing); } } }