I'm trying to use SharpSSH to get a file from a remote SFTP server, and I want to read it out as a stream.
I found:
class Sftp
, which has a Get
method that saves it to a local file -- close
class SshStream
, which might do kind of what I want, but seems disjoint from Sftp
so I might have to implement the SFTP part myself (??)
class ChannelSftp
, which implements SFTP methods like get(String, OutputStream)
, which seems perfect, except it's a low-level class and it's not at all obvious to me how to even instantiate it
It looks like if Sftp
's ChannelSftp SftpChannel
property wasn't private, I could use that and everything would be perfect. I'd like to avoid hacking up SharpSSH if possible, though.
Am I missing something?
I worked something out, and tested it out. Give it a try, and feel free to massage the API.
First off, you will need to surface up a method that allows you to take advantage of the ChannelSftp
methods that call for OutputStream
s instead of destination file names. If you don't want to use reflection to do it, then add this method to the Sftp class and recompile SharpSSH.
public void GetWithStream(string fromFilePath, Tamir.SharpSsh.java.io.OutputStream stream)
{
cancelled = false;
SftpChannel.get(fromFilePath, stream, m_monitor);
}
Next, create a wrapper for the Stream
class that is compatible with Tamir.SharpSsh.java.io.OutputStream
, such as the one below:
using System.IO;
using Tamir.SharpSsh.java.io;
public class GenericSftpOutputStream : OutputStream
{
Stream stream;
public GenericSftpOutputStream(Stream stream)
{
this.stream = stream;
}
public override void Write(byte[] buffer, int offset, int count)
{
stream.Write(buffer, offset, count);
}
public override void Flush()
{
stream.Flush();
}
public override void Close()
{
stream.Close();
}
public override bool CanSeek
{
get { return stream.CanSeek; }
}
public override long Seek(long offset, SeekOrigin origin)
{
return stream.Seek(offset, origin);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (this.stream != null)
{
this.stream.Dispose();
this.stream = null;
}
}
}
With those ingredients, you can now use OpenSSH to stream its data to the stream of your choice, as demonstrated below with a FileStream
.
using System.IO;
using Tamir.SharpSsh;
class Program
{
static void Main(string[] args)
{
var host = "hostname";
var user = "username";
var pass = "password";
var file = "/some/remote/path.txt";
var saveas = @"C:\some\local\path";
var client = new Sftp(host, user, pass);
client.Connect();
using (var target = new GenericSftpOutputStream(File.Open(saveas, FileMode.OpenOrCreate)))
{
client.GetWithStream(file, target);
}
client.Close();
}
}