6

I am using the ssh.net library for performing SFTP operations to work with large data files (>=500MB)

I am having an issue with how to return the data in a non-blocking way.

The ftpClient.DownloadFile() method signature is ok, when writing to a file or if there's some way I can instantiate the stream, but am having problems on how to use it when I want to return a stream without blocking.

All the examples I have seen so far will be writing the download to a Filestream. Nothing that just returns a stream

With .Net's built-in FTP, you just use response.GetResponseStream(), and it streams back the data, without blocking.

The only way round to using it in a return statement was writing to a temporarity file. But this results in it being a blocking operation.

        var tmpFilename = "temp.dat";
        int bufferSize = 4096;
        var sourceFile = "23-04-2015.dat";

        using (var stream = System.IO.File.Create(tmpFilename , bufferSize, System.IO.FileOptions.DeleteOnClose))
        {
            sftpClient.DownloadFile(sourceFile, stream);
            return stream;
        }

I don't want it to block but to stream back the data.

I also would like to avoid creating a temporary file.

Is there an alternative implementation to make it stream back the data?

Or is there an alternative stream I can instantiate(except for MemoryStream), that would work with large files?

tinonetic
  • 7,751
  • 11
  • 54
  • 79
  • The download is over which protocol (i.e: HTTP, TCP)? – Vinicius Ottoni Apr 27 '15 at 13:43
  • I dont get your questioning. How does TCP come in though since it's a non-application protocol....Dont think there such a thing as SFTP over HTTP.... But it's SFTP, over port 22. – tinonetic Apr 28 '15 at 05:38
  • I thought that you want to download first from the SFTP to your app (that could be in WPF or ASP.NET, i.e.). But the download is direct, right? – Vinicius Ottoni Apr 28 '15 at 13:48

2 Answers2

4

This is old question, but I had similar issue. If you want to get the stream directly you can write to MemoryStream.

SftpClient _sftpClient;
_sftpClient = new SftpClient("sftp.server.domain", "MyLoginHere", "MyPasswordHere");
Stream fileBody = new MemoryStream();
_sftpClient.DownloadFile(ftpFile.FullName, fileBody);
fileBody.Position = 0; //dont forget to set the stream position back to beginning

If you want to download file, you can make it in separate thread or as asynchronous call and then call the delegate:

_sftpClient.DownloadFile(ftpFile.FullName, fileBody, YourActionDelegateHere);
  • 2
    That may be fine for small files, but it is the least performant as you are not utilising buffering... you will get `OutOfMemoryException`s for large files. – tinonetic Oct 24 '17 at 10:01
0

Many years later, I had this same issue that took longer to figure out than I'd care to admit. This was one of the top search results, so here's an actual answer: It turns out that SSH.NET does indeed expose an SftpFileStream, just with different methods that you might not see if you're looking for "Download". Instead of sftpClient.DownloadFile(sourceFile, stream), use sftpClient.OpenRead(sourceFile). That will allow you to work directly with the streamed data.

mdk
  • 117
  • 1
  • 11