深度优先

这个家伙好懒,除了文章什么都没留下

0%

【.Net】SSH.NET应用

https://www.cjavapy.com/article/398/

SSH.NET是用于.NET的Secure Shell(SSH-2)库,sftp是通过ssh实现的,本文主要介绍.Net(C#)中,使用SSH.NET对sftp常用操作及工具类代码,包括sftp服务器的连接,文件上传,下载文件,文件删除,文件的位置的移动等操作。

1、SSH.NET安装引用

使用Nuget管理工具搜索 SSH.NET =>找到选择安装

2、SSH.NET操作代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
using NLog;
using Renci.SshNet;
using Renci.SshNet.Sftp;
using ShellProgressBar;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;

namespace PiSftpClient
{
public class SFtpHelper
{
private SftpClient sftp;

private static readonly Logger logger = LogManager.GetLogger("SFtpHelper");

/// <summary>
/// 连接状态
/// </summary>
public bool Connected
{
get
{
return this.sftp.IsConnected;
}
}

/// <summary>
///
/// </summary>
/// <param name="host">sftp的IP</param>
/// <param name="port">sftp的端口</param>
/// <param name="username">sftp的帐户</param>
/// <param name="password">sftp的密码</param>
public SFtpHelper(string host, int port, string username, string password)
{
this.sftp = new SftpClient(host, port, username, password);
}

/// <summary>
/// 连接sftp服务器
/// </summary>
/// <returns>连接状态</returns>
public bool Connect()
{
bool result;
try
{
bool flag = !this.Connected;
if (flag)
{
this.sftp.Connect();
}
result = true;
}
catch (Exception ex)
{
result = false;
logger.Error(string.Format("连接SFTP失败,原因:{0}", ex.Message));
}
return result;
}

/// <summary>
/// 断开连接
/// </summary>
public void Disconnect()
{
try
{
bool flag = this.sftp != null && this.Connected;
if (flag)
{
this.sftp.Disconnect();
}
}
catch (Exception ex)
{
logger.Error(string.Format("断开SFTP失败,原因:{0}", ex.Message));
}
}

/// <summary>
/// 上传文件
/// </summary>
/// <param name="localPath">本地文件路径</param>
/// <param name="remotePath">服务器端文件路径</param>
public void Put(string localPath, string remotePath)
{
try
{
using (FileStream fileStream = File.OpenRead(localPath))
{
this.sftp.UploadFile(fileStream, remotePath, null);
}
}
catch (Exception ex)
{
logger.Error(string.Format("SFTP文件上传失败,原因:{0}", ex.Message));
}
}

/// <summary>
/// 上传文字字节数据
/// </summary>
/// <param name="fileByteArr">文件内容字节</param>
/// <param name="remotePath">上传到服务器的路径</param>
public void Put(byte[] fileByteArr, string remotePath)
{
try
{
Stream input = new MemoryStream(fileByteArr);
this.sftp.UploadFile(input, remotePath, null);
}
catch (Exception ex)
{
logger.Error(string.Format("SFTP文件上传失败,原因:{0}", ex.Message));
}
}

/// <summary>
/// 将sftp服务器的文件下载本地
/// </summary>
/// <param name="remotePath">服务器上的路径</param>
/// <param name="localPath">本地的路径</param>
public void DownloadFile(string remotePath, string localPath)
{
try
{
this.Connect();
MemoryStream stream = new MemoryStream();
this.sftp.DownloadFile(remotePath, stream, UpdateProgress);
File.WriteAllBytes(localPath, stream.ToArray());
}
catch (Exception ex)
{
logger.Error(string.Format("SFTP文件获取失败,原因:{0}", ex.Message));
}
}

private void UpdateProgress(ulong obj)
{
}

/// <summary>
/// 删除ftp服务器上的文件
/// </summary>
/// <param name="remoteFile">服务器上的路径</param>
public void Delete(string remoteFile)
{
try
{
this.sftp.Delete(remoteFile);
}
catch (Exception ex)
{
logger.Error(string.Format("SFTP文件删除失败,原因:{0}", ex.Message));
}
}

/// <summary>
/// 获取ftp服务器上指定路径上的指定前缀的文件名列表
/// </summary>
/// <param name="remotePath">服务器上的路径</param>
/// <param name="fileSuffix">文件名后缀</param>
/// <returns></returns>
public List<string> GetFileList(string remotePath, string fileSuffix)
{
List<string> result;
try
{
IEnumerable<SftpFile> enumerable = this.sftp.ListDirectory(remotePath, null);
result = new List<string>();
foreach (SftpFile current in enumerable)
{
if (current.Name.EndsWith(fileSuffix))
{
result.Add(current.Name);
}
}
}
catch (Exception ex)
{
result = new List<string>();
logger.Error(string.Format("SFTP文件列表获取失败,原因:{0}", ex.Message));
}
return result;
}

/// <summary>
/// ftp服务器端文件移动
/// </summary>
/// <param name="oldRemotePath">原来服务器上路径</param>
/// <param name="newRemotePath">移动后服务器上新路径</param>
public void Move(string oldRemotePath, string newRemotePath)
{
try
{
this.sftp.RenameFile(oldRemotePath, newRemotePath);
}
catch (Exception ex)
{
logger.Error(string.Format("SFTP文件移动失败,原因:{0}", ex.Message));
}
}
}
}

3、例子从树莓派上下载照片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
using NLog;
using PiSftpClient.Mail;
using ShellProgressBar;
using System;
using System.IO;
using System.Linq;

namespace PiSftpClient
{
internal class Program
{
private static readonly Logger logger = LogManager.GetLogger("PiSftpClient");

private static void Main(string[] args)
{
var servicePath = "/opt/docker/camera/pictures/";
var localhostPath = @"F:\pi\pictures\";

var dateStr = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd");
logger.Info($"开始下载 {dateStr} 的照片文件!");

SFtpHelper ftp = new SFtpHelper("192.168.8.100", 22, "root", "123456");

ftp.Connect();
var servicePathDate = $"{servicePath}/{dateStr}/";
var localhostPathDate = $"{localhostPath}/{dateStr}";

if (!Directory.Exists(localhostPathDate))
{
Directory.CreateDirectory(localhostPathDate);
}

var childOptions = new ProgressBarOptions
{
ProgressCharacter = '#',
ForegroundColor = ConsoleColor.Yellow,
ForegroundColorDone = ConsoleColor.DarkGreen,
BackgroundColor = ConsoleColor.DarkGray,
ProgressBarOnBottom = true,
};

var imageFiles = ftp.GetFileList(servicePathDate, ".jpg").OrderBy(p => p).ToList();
logger.Info($"服务器上总共 {imageFiles.Count} 个文件!");
using var pbar = new ProgressBar(imageFiles.Count, "download", childOptions);

for (int i = 0; i < imageFiles.Count; i++)
{
var newName = $"{imageFiles[i].Replace("-", "").Replace(".jpg", "")}{i.ToString().PadLeft(4, '0')}.jpg";

ftp.DownloadFile($"{servicePathDate}/{imageFiles[i]}", $"{localhostPathDate}/{newName}");
pbar.Message = $"[{DateTime.Now:HH:mm:ss}] ({i}/{imageFiles.Count}) downloading {imageFiles[i]}";
pbar.Tick();

logger.Info($"下载成功 ({i}/{imageFiles.Count}) downloading {imageFiles[i]} ");
}

ftp.Disconnect();
logger.Info($"下载完成!");

SendMail();
}

private static void SendMail()
{
string filePath = $"./logs/{DateTime.Now:yyyy-MM-dd}.log";
MailHelper mail = new MailHelper();
MailObject mailObject = new MailObject()
{
toMails = "bfsdfs@yeah.net",
ccMails = "1439084907@qq.com",
Subject = "【树莓派】消息通知",
MailBody = "ok...日志信息见附件!",
FilePaths = filePath
};
var result = mail.Send(mailObject);
}
}
}