| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- using System;
- using System.IO;
- using Renci.SshNet;
- using Renci.SshNet.Sftp;
- using System.Collections.Generic;
- namespace SFTPUtils
- {
- public class SftpClientWithKey
- {
- private SftpClient _sftpClient;
- private readonly string _host;
- private readonly int _port;
- private readonly string _username;
- private readonly string _privateKeyPath;
- /// <summary>
- /// 初始化 SFTP 客户端
- /// </summary>
- /// <param name="host">SFTP 服务器地址</param>
- /// <param name="port">端口(默认22)</param>
- /// <param name="username">用户名</param>
- /// <param name="privateKeyPath">OpenSSH 格式私钥文件路径</param>
- public SftpClientWithKey(string host, int port, string username, string privateKeyPath)
- {
- _host = host;
- _port = port;
- _username = username;
- _privateKeyPath = privateKeyPath;
- }
- /// <summary>
- /// 连接到 SFTP 服务器
- /// </summary>
- public void Connect()
- {
- try
- {
- if (_sftpClient != null && _sftpClient.IsConnected)
- {
- return;
- }
- var keyFiles = new[] { new PrivateKeyFile(_privateKeyPath) };
- var connectionInfo = new ConnectionInfo(_host, _port, _username,
- new PrivateKeyAuthenticationMethod(_username, keyFiles));
- _sftpClient = new SftpClient(connectionInfo);
- _sftpClient.Connect();
- }
- catch (Exception ex)
- {
- throw new Exception($"SFTP 连接失败: {ex.Message}", ex);
- }
- }
- /// <summary>
- /// 断开连接
- /// </summary>
- public void Disconnect()
- {
- if (_sftpClient != null && _sftpClient.IsConnected)
- {
- _sftpClient.Disconnect();
- }
- }
- /// <summary>
- /// 上传文件到 SFTP 服务器
- /// </summary>
- /// <param name="localFilePath">本地文件路径</param>
- /// <param name="remoteDirectory">远程目录</param>
- /// <param name="remoteFileName">远程文件名(可选,如果为空则使用本地文件名)</param>
- /// <returns>上传成功返回 true</returns>
- public bool UploadFile(string localFilePath, string remoteDirectory, string remoteFileName = null)
- {
- if (!File.Exists(localFilePath))
- {
- throw new FileNotFoundException("本地文件不存在", localFilePath);
- }
- Connect();
- try
- {
- // 确保远程目录存在
- CreateRemoteDirectory(remoteDirectory);
- // 确定远程文件名
- string finalRemoteFileName = string.IsNullOrEmpty(remoteFileName)
- ? Path.GetFileName(localFilePath)
- : remoteFileName;
- string remoteFilePath = $"{remoteDirectory.TrimEnd('/')}/{finalRemoteFileName}";
- using (var fileStream = new FileStream(localFilePath, FileMode.Open))
- {
- _sftpClient.UploadFile(fileStream, remoteFilePath);
- }
- return true;
- }
- catch (Exception ex)
- {
- throw new Exception($"文件上传失败: {ex.Message}", ex);
- }
- }
- /// <summary>
- /// 创建远程目录(如果不存在)
- /// </summary>
- /// <param name="remoteDirectory">远程目录路径</param>
- private void CreateRemoteDirectory(string remoteDirectory)
- {
- try
- {
- var directories = remoteDirectory.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
- string currentPath = string.Empty;
- foreach (var directory in directories)
- {
- currentPath += "/" + directory;
- if (!_sftpClient.Exists(currentPath))
- {
- _sftpClient.CreateDirectory(currentPath);
- }
- }
- }
- catch (Exception ex)
- {
- throw new Exception($"创建远程目录失败: {ex.Message}", ex);
- }
- }
- /// <summary>
- /// 检查文件是否存在
- /// </summary>
- /// <param name="remoteFilePath">远程文件路径</param>
- /// <returns>存在返回 true</returns>
- public bool FileExists(string remoteFilePath)
- {
- Connect();
- return _sftpClient.Exists(remoteFilePath);
- }
- /// <summary>
- /// 列出远程目录中的文件
- /// </summary>
- /// <param name="remoteDirectory">远程目录</param>
- /// <returns>文件列表</returns>
- public IEnumerable<ISftpFile> ListFiles(string remoteDirectory)
- {
- Connect();
- return _sftpClient.ListDirectory(remoteDirectory);
- }
- /// <summary>
- /// 删除远程文件
- /// </summary>
- /// <param name="remoteFilePath">远程文件路径</param>
- /// <returns>删除成功返回 true</returns>
- public bool DeleteFile(string remoteFilePath)
- {
- Connect();
- if (_sftpClient.Exists(remoteFilePath))
- {
- _sftpClient.DeleteFile(remoteFilePath);
- return true;
- }
- return false;
- }
- /// <summary>
- /// 释放资源
- /// </summary>
- public void Dispose()
- {
- Disconnect();
- _sftpClient?.Dispose();
- }
- }
- }
|