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;
///
/// 初始化 SFTP 客户端
///
/// SFTP 服务器地址
/// 端口(默认22)
/// 用户名
/// OpenSSH 格式私钥文件路径
public SftpClientWithKey(string host, int port, string username, string privateKeyPath)
{
_host = host;
_port = port;
_username = username;
_privateKeyPath = privateKeyPath;
}
///
/// 连接到 SFTP 服务器
///
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);
}
}
///
/// 断开连接
///
public void Disconnect()
{
if (_sftpClient != null && _sftpClient.IsConnected)
{
_sftpClient.Disconnect();
}
}
///
/// 上传文件到 SFTP 服务器
///
/// 本地文件路径
/// 远程目录
/// 远程文件名(可选,如果为空则使用本地文件名)
/// 上传成功返回 true
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);
}
}
///
/// 创建远程目录(如果不存在)
///
/// 远程目录路径
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);
}
}
///
/// 检查文件是否存在
///
/// 远程文件路径
/// 存在返回 true
public bool FileExists(string remoteFilePath)
{
Connect();
return _sftpClient.Exists(remoteFilePath);
}
///
/// 列出远程目录中的文件
///
/// 远程目录
/// 文件列表
public IEnumerable ListFiles(string remoteDirectory)
{
Connect();
return _sftpClient.ListDirectory(remoteDirectory);
}
///
/// 删除远程文件
///
/// 远程文件路径
/// 删除成功返回 true
public bool DeleteFile(string remoteFilePath)
{
Connect();
if (_sftpClient.Exists(remoteFilePath))
{
_sftpClient.DeleteFile(remoteFilePath);
return true;
}
return false;
}
///
/// 释放资源
///
public void Dispose()
{
Disconnect();
_sftpClient?.Dispose();
}
}
}