Skip to content

Add support for resuming SFTP file upload/download - #864

Open
zybexXL wants to merge 7 commits into
sshnet:developfrom
zybexXL:SFTP_resume
Open

Add support for resuming SFTP file upload/download#864
zybexXL wants to merge 7 commits into
sshnet:developfrom
zybexXL:SFTP_resume

Conversation

@zybexXL

@zybexXL zybexXL commented Aug 27, 2021

Copy link
Copy Markdown
Contributor

This adds resume capability to SftpClient.UploadFile() , SftpClient.DownloadFile(), as well as to the BeginUploadFile() and BeginDownloadFile() variants.

The API remains unchanged. Resume is triggered simply by changing the current Position of the input/output stream which is given as an argument to these functions:

  • Setting a non-zero position on the input Stream for UploadFile() triggers an Append to the remote file. It's up to the caller to first check the current size of the remote file and set the local position accordingly!
  • Setting a non-zero position on the output Stream for DownloadFile() triggers a resume of the download at the given position.

This also does NOT check if the server supports Resume, though all servers I've tested so far do support it.

Comment thread src/Renci.SshNet/Sftp/SftpFileReader.cs Outdated
Comment thread src/Renci.SshNet/ServiceFactory.cs Outdated
Comment thread src/Renci.SshNet/SftpClient.cs
Comment thread src/Renci.SshNet/SftpClient.cs
Comment thread src/Renci.SshNet/SftpClient.cs Outdated
@zybexXL

zybexXL commented Nov 1, 2023

Copy link
Copy Markdown
Contributor Author

I've rebased this PR, please review and consider merging.

@WojciechNagorski WojciechNagorski left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked this PR and it looks great!

I just want you to provide two integration tests for upload and download.
You can use similar mechanism, like in

public void Common_LossOfNetworkConnectivityDisconnectAndConnect()

bool vmNetworkConnectionDisabled = false;
SshConnectionRestorer disruptor = null;
try
{
    using (var client = new SftpClient(_connectionInfoFactory.Create()))
    {
        client.Connect();
        
        // <-- Start upload/download file

        disruptor = _sshConnectionDisruptor.BreakConnections();
        vmNetworkConnectionDisabled = true;

        WaitForConnectionInterruption(client);
        // disconnect while network connectivity is lost
        client.Disconnect();

        Assert.IsFalse(client.IsConnected);
        
        disruptor.RestoreConnections();
        vmNetworkConnectionDisabled = false;

        // connect when network connectivity is restored
        client.Connect();

        // <-- Resume download/upload file

        client.Dispose();
    }
}
finally
{
    if (vmNetworkConnectionDisabled)
    {
        disruptor.RestoreConnections();
    }
    disruptor?.Dispose();
}

@zybexXL

zybexXL commented Nov 20, 2023

Copy link
Copy Markdown
Contributor Author

@WojciechNagorski
This type of Resume test won't work as the test file may well finish upload/download before the Disruptor kicks in, especially if the test server is in localhost.
Better to upload a small file, then reconnect and append some more data, then check if the filesize is as expected. The download resume test can download the file in 2 chunks and check if it's correct. OK ?

@WojciechNagorski

WojciechNagorski commented Dec 20, 2023

Copy link
Copy Markdown
Collaborator

Sorry for delay. It's correct.

Yazwh0 added a commit to Yazwh0/bennybox that referenced this pull request Aug 10, 2026
…port

Clips is a new dedicated content type (nav page, own DB tables, own source
pipeline) for one-off media that isn't a movie or a TV episode - sports
broadcasts, specials - with no season/episode number and no TMDb lookup
attempted, since a metadata-matching guess is more likely wrong than helpful
for this kind of title.

Downloads lets any movie, episode, or clip be pulled onto the local machine
for offline/faster playback. Downloaded content lands in one auto-managed
Local Folder profile and is scanned through the exact same FolderMediaScanner
pipeline as any other local library, so it gets badges/favorites/search for
free with no new browsing infrastructure. Once downloaded, playback
transparently prefers the local copy over re-streaming the original, while
watch progress stays keyed to the original item so resume position isn't
fragmented. A new Downloads panel shows live progress with Cancel/Retry/
Delete, and Series gets Download Season/Download All actions.

Interrupted downloads (a dropped connection, or the app closing mid-transfer)
resume from where they left off for Xtream and Local Folder sources via HTTP
Range requests and file-seek respectively. SFTP downloads restart cleanly
from scratch instead - confirmed via live testing against a real server that
the SSH.NET version in use has no seekable read-side stream and no public
offset-based read API, a known unimplemented feature upstream (sshnet/SSH.NET#864).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRRhvjLGh6hy2NxGytZsWJ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants