<PackageReference Include="SSH.NET" Version="2016.0.0-beta2" />

ScpClient

public class ScpClient : BaseClient
Provides SCP client functionality.
using Renci.SshNet.Channels; using Renci.SshNet.Common; using System; using System.IO; using System.Text; using System.Text.RegularExpressions; namespace Renci.SshNet { public class ScpClient : BaseClient { private static readonly Regex FileInfoRe = new Regex("C(?<mode>\\d{4}) (?<length>\\d+) (?<filename>.+)"); private static char[] _byteToChar; public TimeSpan OperationTimeout { get; set; } public uint BufferSize { get; set; } public event EventHandler<ScpDownloadEventArgs> Downloading; public event EventHandler<ScpUploadEventArgs> Uploading; public ScpClient(ConnectionInfo connectionInfo) : this(connectionInfo, false) { } public ScpClient(string host, int port, string username, string password) : this(new PasswordConnectionInfo(host, port, username, password), true) { } public ScpClient(string host, string username, string password) : this(host, ConnectionInfo.DefaultPort, username, password) { } public ScpClient(string host, int port, string username, params PrivateKeyFile[] keyFiles) : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true) { } public ScpClient(string host, string username, params PrivateKeyFile[] keyFiles) : this(host, ConnectionInfo.DefaultPort, username, keyFiles) { } private ScpClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo) : this(connectionInfo, ownsConnectionInfo, new ServiceFactory()) { } internal ScpClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo, IServiceFactory serviceFactory) : base(connectionInfo, ownsConnectionInfo, serviceFactory) { OperationTimeout = Renci.SshNet.Session.InfiniteTimeSpan; BufferSize = 16384; if (_byteToChar == null) { _byteToChar = new char[128]; char c = ''; for (int i = 0; i < 128; i++) { char[] byteToChar = _byteToChar; int num = i; char num2 = c; c = (char)(num2 + 1); byteToChar[num] = num2; } } } public void Upload(Stream source, string path) { PipeStream input = base.ServiceFactory.CreatePipeStream(); try { using (IChannelSession channelSession = base.Session.CreateChannelSession()) { channelSession.DataReceived += delegate(object sender, ChannelDataEventArgs e) { input.Write(e.Data, 0, e.Data.Length); }; channelSession.Open(); int num = path.LastIndexOfAny(new char[2] { '\\', '/' }); if (num != -1) { string arg = path.Substring(0, num); string text = path.Substring(num + 1); channelSession.SendExecRequest($"""{arg}"""); CheckReturnCode(input); path = text; } InternalUpload(channelSession, input, source, path); channelSession.Close(); } } finally { if (input != null) ((IDisposable)input).Dispose(); } } public void Download(string filename, Stream destination) { if (filename.IsNullOrWhiteSpace()) throw new ArgumentException("filename"); if (destination == null) throw new ArgumentNullException("destination"); PipeStream input = base.ServiceFactory.CreatePipeStream(); try { using (IChannelSession channelSession = base.Session.CreateChannelSession()) { channelSession.DataReceived += delegate(object sender, ChannelDataEventArgs e) { input.Write(e.Data, 0, e.Data.Length); }; channelSession.Open(); channelSession.SendExecRequest($"""{filename}"""); SendConfirmation(channelSession); string text = ReadString(input); Match match = FileInfoRe.Match(text); if (match.Success) { SendConfirmation(channelSession); match.Result("${mode}"); long length = long.Parse(match.Result("${length}")); string filename2 = match.Result("${filename}"); InternalDownload(channelSession, input, destination, filename2, length); } else SendConfirmation(channelSession, 1, $"""{text}"""); channelSession.Close(); } } finally { if (input != null) ((IDisposable)input).Dispose(); } } private void InternalSetTimestamp(IChannelSession channel, Stream input, DateTime lastWriteTime, DateTime lastAccessime) { DateTime d = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); TimeSpan timeSpan = lastWriteTime - d; long num = (long)timeSpan.TotalSeconds; timeSpan = lastAccessime - d; long num2 = (long)timeSpan.TotalSeconds; SendData(channel, $"""{num}""{num2}"""); CheckReturnCode(input); } private void InternalUpload(IChannelSession channel, Stream input, Stream source, string filename) { long length = source.Length; SendData(channel, $"""{length}""{Path.GetFileName(filename)}"""); CheckReturnCode(input); byte[] array = new byte[BufferSize]; int num = source.Read(array, 0, array.Length); long num2 = 0; while (num > 0) { SendData(channel, array, num); num2 += num; RaiseUploadingEvent(filename, length, num2); num = source.Read(array, 0, array.Length); } SendConfirmation(channel); CheckReturnCode(input); } private void InternalDownload(IChannel channel, Stream input, Stream output, string filename, long length) { byte[] buffer = new byte[Math.Min(length, BufferSize)]; long num = length; do { int num2 = input.Read(buffer, 0, (int)Math.Min(num, BufferSize)); output.Write(buffer, 0, num2); RaiseDownloadingEvent(filename, length, length - num); num -= num2; } while (num > 0); output.Flush(); RaiseDownloadingEvent(filename, length, length - num); SendConfirmation(channel); CheckReturnCode(input); } private void RaiseDownloadingEvent(string filename, long size, long downloaded) { if (this.Downloading != null) this.Downloading(this, new ScpDownloadEventArgs(filename, size, downloaded)); } private void RaiseUploadingEvent(string filename, long size, long uploaded) { if (this.Uploading != null) this.Uploading(this, new ScpUploadEventArgs(filename, size, uploaded)); } private void SendConfirmation(IChannel channel) { SendData(channel, new byte[1]); } private void SendConfirmation(IChannel channel, byte errorCode, string message) { SendData(channel, new byte[1] { errorCode }); SendData(channel, $"{message}"""); } private static void CheckReturnCode(Stream input) { if (ReadByte(input) > 0) throw new ScpException(ReadString(input)); } private static void SendData(IChannel channel, string command) { channel.SendData(SshData.Utf8.GetBytes(command)); } private static void SendData(IChannel channel, byte[] buffer, int length) { channel.SendData(buffer, 0, length); } private static void SendData(IChannel channel, byte[] buffer) { channel.SendData(buffer); } private static int ReadByte(Stream stream) { int num = stream.ReadByte(); if (num == -1) throw new SshException("Stream has been closed."); return num; } private static string ReadString(Stream stream) { bool flag = false; StringBuilder stringBuilder = new StringBuilder(); int num = ReadByte(stream); if (num == 1 || num == 2) { flag = true; num = ReadByte(stream); } for (char c = _byteToChar[num]; c != '\n'; c = _byteToChar[num]) { stringBuilder.Append(c); num = ReadByte(stream); } if (flag) throw new ScpException(stringBuilder.ToString()); return stringBuilder.ToString(); } } }