Skip to content

Commit a6f9519

Browse files
author
Pedro Fonseca
committed
Add support for resuming file upload/download
1 parent 508fc87 commit a6f9519

14 files changed

+260
-239
lines changed

src/Renci.SshNet/IServiceFactory.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,17 +83,18 @@ internal partial interface IServiceFactory
8383
/// <exception cref="SshConnectionException">No key exchange algorithm is supported by both client and server.</exception>
8484
IKeyExchange CreateKeyExchange(IDictionary<string, Type> clientAlgorithms, string[] serverAlgorithms);
8585

86-
/// <summary>
86+
/// <summary>
8787
/// Creates an <see cref="ISftpFileReader"/> for the specified file and with the specified
8888
/// buffer size.
8989
/// </summary>
9090
/// <param name="fileName">The file to read.</param>
9191
/// <param name="sftpSession">The SFTP session to use.</param>
9292
/// <param name="bufferSize">The size of buffer.</param>
93+
/// <param name="offset">The offset to resume from.</param>
9394
/// <returns>
9495
/// An <see cref="ISftpFileReader"/>.
9596
/// </returns>
96-
ISftpFileReader CreateSftpFileReader(string fileName, ISftpSession sftpSession, uint bufferSize);
97+
ISftpFileReader CreateSftpFileReader(string fileName, ISftpSession sftpSession, uint bufferSize, ulong offset = 0);
9798

9899
/// <summary>
99100
/// Creates a new <see cref="ISftpResponseFactory"/> instance.

src/Renci.SshNet/ServiceFactory.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,11 @@ public INetConfSession CreateNetConfSession(ISession session, int operationTimeo
138138
/// <param name="fileName">The file to read.</param>
139139
/// <param name="sftpSession">The SFTP session to use.</param>
140140
/// <param name="bufferSize">The size of buffer.</param>
141+
/// <param name="offset">The offset to resume from.</param>
141142
/// <returns>
142143
/// An <see cref="ISftpFileReader"/>.
143144
/// </returns>
144-
public ISftpFileReader CreateSftpFileReader(string fileName, ISftpSession sftpSession, uint bufferSize)
145+
public ISftpFileReader CreateSftpFileReader(string fileName, ISftpSession sftpSession, uint bufferSize, ulong offset = 0)
145146
{
146147
const int defaultMaxPendingReads = 3;
147148

@@ -163,7 +164,7 @@ public ISftpFileReader CreateSftpFileReader(string fileName, ISftpSession sftpSe
163164
{
164165
var fileAttributes = sftpSession.EndLStat(statAsyncResult);
165166
fileSize = fileAttributes.Size;
166-
maxPendingReads = Math.Min(10, (int) Math.Ceiling((double) fileAttributes.Size / chunkSize) + 1);
167+
maxPendingReads = Math.Min(10, (int) Math.Ceiling((double)(fileSize - (long)offset) / chunkSize) + 1);
167168
}
168169
catch (SshException ex)
169170
{
@@ -173,7 +174,7 @@ public ISftpFileReader CreateSftpFileReader(string fileName, ISftpSession sftpSe
173174
DiagnosticAbstraction.Log(string.Format("Failed to obtain size of file. Allowing maximum {0} pending reads: {1}", maxPendingReads, ex));
174175
}
175176

176-
return sftpSession.CreateFileReader(handle, sftpSession, chunkSize, maxPendingReads, fileSize);
177+
return sftpSession.CreateFileReader(handle, sftpSession, chunkSize, maxPendingReads, fileSize, offset);
177178
}
178179

179180
/// <summary>

src/Renci.SshNet/Sftp/ISftpSession.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,10 +494,11 @@ void RequestWrite(byte[] handle,
494494
/// <param name="chunkSize">The maximum number of bytes to read with each chunk.</param>
495495
/// <param name="maxPendingReads">The maximum number of pending reads.</param>
496496
/// <param name="fileSize">The size of the file or <see langword="null"/> when the size could not be determined.</param>
497+
/// <param name="offset">The offset to resume from.</param>
497498
/// <returns>
498499
/// An <see cref="ISftpFileReader"/> for reading the content of the file represented by the
499500
/// specified <paramref name="handle"/>.
500501
/// </returns>
501-
ISftpFileReader CreateFileReader(byte[] handle, ISftpSession sftpSession, uint chunkSize, int maxPendingReads, long? fileSize);
502+
ISftpFileReader CreateFileReader(byte[] handle, ISftpSession sftpSession, uint chunkSize, int maxPendingReads, long? fileSize, ulong offset = 0);
502503
}
503504
}

src/Renci.SshNet/Sftp/SftpFileReader.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,15 @@ internal sealed class SftpFileReader : ISftpFileReader
5656
/// <param name="chunkSize">The size of a individual read-ahead chunk.</param>
5757
/// <param name="maxPendingReads">The maximum number of pending reads.</param>
5858
/// <param name="fileSize">The size of the file, if known; otherwise, <see langword="null"/>.</param>
59-
public SftpFileReader(byte[] handle, ISftpSession sftpSession, uint chunkSize, int maxPendingReads, long? fileSize)
59+
/// <param name="offset">The offset to resume from.</param>
60+
public SftpFileReader(byte[] handle, ISftpSession sftpSession, uint chunkSize, int maxPendingReads, long? fileSize, ulong offset = 0)
6061
{
6162
_handle = handle;
6263
_sftpSession = sftpSession;
6364
_chunkSize = chunkSize;
6465
_fileSize = fileSize;
66+
_offset = offset;
67+
_readAheadOffset = offset;
6568
_semaphore = new SemaphoreLight(maxPendingReads);
6669
_queue = new Dictionary<int, BufferedRead>(maxPendingReads);
6770
_readLock = new object();

0 commit comments

Comments
 (0)