-
-
Notifications
You must be signed in to change notification settings - Fork 957
Add async support to SftpClient and SftpFileStream #819
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
ca1a59f
5f74049
d5c80f5
d578af7
c37a884
ed8e789
a33cab8
2235756
6fb5be2
b7fd333
85839e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,12 @@ | |
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Text; | ||
using System.Threading; | ||
using Renci.SshNet.Sftp; | ||
using Renci.SshNet.Common; | ||
#if FEATURE_TAP | ||
using System.Threading.Tasks; | ||
#endif | ||
|
||
namespace Renci.SshNet | ||
{ | ||
|
@@ -488,6 +492,22 @@ public interface ISftpClient | |
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception> | ||
void DeleteFile(string path); | ||
|
||
#if FEATURE_TAP | ||
/// <summary> | ||
/// Asynchronously deletes remote file specified by path. | ||
/// </summary> | ||
/// <param name="path">File to be deleted path.</param> | ||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param> | ||
/// <returns>A <see cref="Task"/> that represents the asynchronous delete operation.</returns> | ||
/// <exception cref="ArgumentException"><paramref name="path"/> is <b>null</b> or contains only whitespace characters.</exception> | ||
/// <exception cref="SshConnectionException">Client is not connected.</exception> | ||
/// <exception cref="SftpPathNotFoundException"><paramref name="path"/> was not found on the remote host.</exception> | ||
/// <exception cref="SftpPermissionDeniedException">Permission to delete the file was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception> | ||
/// <exception cref="SshException">A SSH error where <see cref="Exception.Message"/> is the message from the remote host.</exception> | ||
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception> | ||
Task DeleteFileAsync(string path, CancellationToken cancellationToken); | ||
#endif | ||
|
||
/// <summary> | ||
/// Downloads remote file specified by the path into the stream. | ||
/// </summary> | ||
|
@@ -506,6 +526,24 @@ public interface ISftpClient | |
/// </remarks> | ||
void DownloadFile(string path, Stream output, Action<ulong> downloadCallback = null); | ||
|
||
#if FEATURE_TAP | ||
/// <summary> | ||
/// Asynchronously downloads remote file specified by the path into the stream. | ||
/// </summary> | ||
/// <param name="path">File to download.</param> | ||
/// <param name="output">Stream to write the file into.</param> | ||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param> | ||
/// <returns>A <see cref="Task"/> that represents the asynchronous download operation.</returns> | ||
/// <exception cref="ArgumentNullException"><paramref name="output" /> is <b>null</b>.</exception> | ||
/// <exception cref="ArgumentException"><paramref name="path" /> is <b>null</b> or contains only whitespace characters.</exception> | ||
/// <exception cref="SshConnectionException">Client is not connected.</exception> | ||
/// <exception cref="SftpPermissionDeniedException">Permission to perform the operation was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception> | ||
/// <exception cref="SftpPathNotFoundException"><paramref name="path"/> was not found on the remote host.</exception>/// | ||
/// <exception cref="SshException">A SSH error where <see cref="Exception.Message" /> is the message from the remote host.</exception> | ||
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception> | ||
Task DownloadFileAsync(string path, Stream output, CancellationToken cancellationToken); | ||
#endif | ||
|
||
/// <summary> | ||
/// Ends an asynchronous file downloading into the stream. | ||
/// </summary> | ||
|
@@ -653,6 +691,22 @@ public interface ISftpClient | |
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception> | ||
SftpFileSytemInformation GetStatus(string path); | ||
|
||
#if FEATURE_TAP | ||
/// <summary> | ||
/// Asynchronously gets status using [email protected] request. | ||
/// </summary> | ||
/// <param name="path">The path.</param> | ||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param> | ||
/// <returns> | ||
/// A <see cref="Task{SftpFileSytemInformation}"/> that represents the status operation. | ||
/// The task result contains the <see cref="SftpFileSytemInformation"/> instance that contains file status information. | ||
/// </returns> | ||
/// <exception cref="SshConnectionException">Client is not connected.</exception> | ||
/// <exception cref="ArgumentNullException"><paramref name="path" /> is <b>null</b>.</exception> | ||
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception> | ||
Task<SftpFileSytemInformation> GetStatusAsync(string path, CancellationToken cancellationToken); | ||
#endif | ||
|
||
/// <summary> | ||
/// Retrieves list of files in remote directory. | ||
/// </summary> | ||
|
@@ -668,6 +722,25 @@ public interface ISftpClient | |
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception> | ||
IEnumerable<SftpFile> ListDirectory(string path, Action<int> listCallback = null); | ||
|
||
#if FEATURE_TAP | ||
|
||
/// <summary> | ||
/// Asynchronously retrieves list of files in remote directory. | ||
/// </summary> | ||
/// <param name="path">The path.</param> | ||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param> | ||
/// <returns> | ||
/// A <see cref="Task{IEnumerable}"/> that represents the asynchronous list operation. | ||
/// The task result contains an enumerable collection of <see cref="SftpFile"/> for the files in the directory specified by <paramref name="path" />. | ||
/// </returns> | ||
/// <exception cref="ArgumentNullException"><paramref name="path" /> is <b>null</b>.</exception> | ||
/// <exception cref="SshConnectionException">Client is not connected.</exception> | ||
/// <exception cref="SftpPermissionDeniedException">Permission to list the contents of the directory was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception> | ||
/// <exception cref="SshException">A SSH error where <see cref="Exception.Message" /> is the message from the remote host.</exception> | ||
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception> | ||
Task<IEnumerable<SftpFile>> ListDirectoryAsync(string path, CancellationToken cancellationToken); | ||
#endif | ||
|
||
/// <summary> | ||
/// Opens a <see cref="SftpFileStream"/> on the specified path with read/write access. | ||
/// </summary> | ||
|
@@ -695,6 +768,24 @@ public interface ISftpClient | |
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception> | ||
SftpFileStream Open(string path, FileMode mode, FileAccess access); | ||
|
||
#if FEATURE_TAP | ||
/// <summary> | ||
/// Asynchronously opens a <see cref="SftpFileStream"/> on the specified path, with the specified mode and access. | ||
/// </summary> | ||
/// <param name="path">The file to open.</param> | ||
/// <param name="mode">A <see cref="FileMode"/> 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.</param> | ||
/// <param name="access">A <see cref="FileAccess"/> value that specifies the operations that can be performed on the file.</param> | ||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param> | ||
/// <returns> | ||
/// A <see cref="Task{SftpFileStream}"/> that represents the asynchronous open operation. | ||
/// The task result contains the <see cref="SftpFileStream"/> that provides access to the specified file, with the specified mode and access. | ||
/// </returns> | ||
/// <exception cref="ArgumentNullException"><paramref name="path"/> is <b>null</b>.</exception> | ||
/// <exception cref="SshConnectionException">Client is not connected.</exception> | ||
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception> | ||
Task<SftpFileStream> OpenAsync(string path, FileMode mode, FileAccess access, CancellationToken cancellationToken); | ||
#endif | ||
|
||
/// <summary> | ||
/// Opens an existing file for reading. | ||
/// </summary> | ||
|
@@ -833,6 +924,22 @@ public interface ISftpClient | |
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception> | ||
void RenameFile(string oldPath, string newPath); | ||
|
||
#if FEATURE_TAP | ||
/// <summary> | ||
/// Asynchronously renames remote file from old path to new path. | ||
/// </summary> | ||
/// <param name="oldPath">Path to the old file location.</param> | ||
/// <param name="newPath">Path to the new file location.</param> | ||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param> | ||
/// <returns>A <see cref="Task"/> that represents the asynchronous rename operation.</returns> | ||
/// <exception cref="ArgumentNullException"><paramref name="oldPath"/> is <b>null</b>. <para>-or-</para> or <paramref name="newPath"/> is <b>null</b>.</exception> | ||
/// <exception cref="SshConnectionException">Client is not connected.</exception> | ||
/// <exception cref="SftpPermissionDeniedException">Permission to rename the file was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception> | ||
/// <exception cref="SshException">A SSH error where <see cref="Exception.Message"/> is the message from the remote host.</exception> | ||
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception> | ||
Task RenameFileAsync(string oldPath, string newPath, CancellationToken cancellationToken); | ||
#endif | ||
|
||
/// <summary> | ||
/// Renames remote file from old path to new path. | ||
/// </summary> | ||
|
@@ -917,6 +1024,27 @@ public interface ISftpClient | |
/// </remarks> | ||
void UploadFile(Stream input, string path, bool canOverride, Action<ulong> uploadCallback = null); | ||
|
||
#if FEATURE_TAP | ||
/// <summary> | ||
/// Asynchronously uploads stream into remote file. | ||
/// </summary> | ||
/// <param name="input">Data input stream.</param> | ||
/// <param name="path">Remote file path.</param> | ||
/// <param name="canOverride">if set to <c>true</c> then existing file will be overwritten.</param> | ||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param> | ||
/// <returns>A <see cref="Task"/> that represents the asynchronous upload operation.</returns> | ||
/// <exception cref="ArgumentNullException"><paramref name="input" /> is <b>null</b>.</exception> | ||
/// <exception cref="ArgumentException"><paramref name="path" /> is <b>null</b> or contains only whitespace characters.</exception> | ||
/// <exception cref="SshConnectionException">Client is not connected.</exception> | ||
/// <exception cref="SftpPermissionDeniedException">Permission to upload the file was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception> | ||
/// <exception cref="SshException">A SSH error where <see cref="Exception.Message" /> is the message from the remote host.</exception> | ||
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception> | ||
/// <remarks> | ||
/// Method calls made by this method to <paramref name="input" />, may under certain conditions result in exceptions thrown by the stream. | ||
/// </remarks> | ||
Task UploadFileAsync(Stream input, string path, bool canOverride, CancellationToken cancellationToken); | ||
#endif | ||
|
||
/// <summary> | ||
/// Writes the specified byte array to the specified file, and closes the file. | ||
/// </summary> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ | |
<AssemblyOriginatorKeyFile>../Renci.SshNet.snk</AssemblyOriginatorKeyFile> | ||
<LangVersion>5</LangVersion> | ||
<SignAssembly>true</SignAssembly> | ||
<TargetFrameworks>net35;net40;netstandard1.3;netstandard2.0</TargetFrameworks> | ||
<TargetFrameworks>net35;net40;net46;netstandard1.3;netstandard2.0</TargetFrameworks> | ||
IgorMilavec marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see no reason for adding .NET 4.6 support at this stage. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or maybe drop some target frameworks? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I have no details on what exactly is broken. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. net46 target is needed to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @IgorMilavec, is it ok for you to target .NET Framework 4.7.2 (or 4.8) instead? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, I've raised the target to net472. |
||
</PropertyGroup> | ||
|
||
<!-- | ||
|
@@ -38,10 +38,13 @@ | |
<PropertyGroup Condition=" '$(TargetFramework)' == 'net40' "> | ||
<DefineConstants>FEATURE_STRINGBUILDER_CLEAR;FEATURE_HASHALGORITHM_DISPOSE;FEATURE_REGEX_COMPILE;FEATURE_BINARY_SERIALIZATION;FEATURE_RNG_CREATE;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_SELECT;FEATURE_SOCKET_POLL;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_DNS_SYNC;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_HMAC_RIPEMD160;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_ENCODING_ASCII;FEATURE_ECDSA</DefineConstants> | ||
</PropertyGroup> | ||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net46' "> | ||
<DefineConstants>FEATURE_STRINGBUILDER_CLEAR;FEATURE_HASHALGORITHM_DISPOSE;FEATURE_REGEX_COMPILE;FEATURE_BINARY_SERIALIZATION;FEATURE_RNG_CREATE;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_SELECT;FEATURE_SOCKET_POLL;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_DNS_SYNC;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_HMAC_RIPEMD160;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_ENCODING_ASCII;FEATURE_ECDSA;FEATURE_TAP</DefineConstants> | ||
</PropertyGroup> | ||
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' "> | ||
<DefineConstants>FEATURE_STRINGBUILDER_CLEAR;FEATURE_HASHALGORITHM_DISPOSE;FEATURE_ENCODING_ASCII;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_RNG_CREATE;FEATURE_SOCKET_TAP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_SELECT;FEATURE_SOCKET_POLL;FEATURE_SOCKET_DISPOSE;FEATURE_DNS_TAP;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512</DefineConstants> | ||
<DefineConstants>FEATURE_STRINGBUILDER_CLEAR;FEATURE_HASHALGORITHM_DISPOSE;FEATURE_ENCODING_ASCII;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_RNG_CREATE;FEATURE_SOCKET_TAP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_SELECT;FEATURE_SOCKET_POLL;FEATURE_SOCKET_DISPOSE;FEATURE_DNS_TAP;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_TAP</DefineConstants> | ||
</PropertyGroup> | ||
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1' "> | ||
<DefineConstants>FEATURE_STRINGBUILDER_CLEAR;FEATURE_HASHALGORITHM_DISPOSE;FEATURE_ENCODING_ASCII;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_RNG_CREATE;FEATURE_SOCKET_TAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_SELECT;FEATURE_SOCKET_POLL;FEATURE_SOCKET_DISPOSE;FEATURE_DNS_SYNC;FEATURE_DNS_APM;FEATURE_DNS_TAP;FEATURE_STREAM_APM;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_ECDSA</DefineConstants> | ||
<DefineConstants>FEATURE_STRINGBUILDER_CLEAR;FEATURE_HASHALGORITHM_DISPOSE;FEATURE_ENCODING_ASCII;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_RNG_CREATE;FEATURE_SOCKET_TAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_SELECT;FEATURE_SOCKET_POLL;FEATURE_SOCKET_DISPOSE;FEATURE_DNS_SYNC;FEATURE_DNS_APM;FEATURE_DNS_TAP;FEATURE_STREAM_APM;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_ECDSA;FEATURE_TAP</DefineConstants> | ||
</PropertyGroup> | ||
</Project> |
Uh oh!
There was an error while loading. Please reload this page.