SSH.NET上传SFTP文件时连接被拒绝或超时
多数情况不是代码写错,而是服务端SSH配置没开SFTP子系统或防火墙拦了22端口。先用
ssh -v user@host在终端确认基础SSH连得通;若能连但
SftpClient报
SocketException或
TimeoutException,重点检查
Renci.SshNet.ConnectionInfo里
Port是否显式设为22(默认是22,但某些私有SFTP服务跑在非标端口)。
常见疏漏点:
ConnectionInfo构造时没传
PrivateKeyFile或
PasswordConnectionInfo,却调用了
new SftpClient(conn)——会静默 fallback 到无认证模式,直接被拒 使用私钥时没调用
privateKey.Load(<code>passphrase)(如有口令),导致
AuthenticationException服务器启用了
ForceCommand internal-sftp但禁用了
chroot外的路径访问,
UploadFile指定的远程路径必须是绝对路径且在受限目录内
FluentFTP上传大文件时内存暴涨或卡死
FluentFTP默认用
FileStream读取本地文件再分块上传,对>100MB的文件容易触发GC压力或
OutOfMemoryException。关键要改用流式上传而非全量加载:
正确做法是传
Stream而非
string路径:
using var fileStream = File.OpenRead(@"C:\large.zip"); await client.UploadAsync(fileStream, "/remote/large.zip");
注意:
别用UploadAsync(string, string)重载——它内部会
File.ReadAllBytes确保
FtpClient已设置
client.DataConnectionType = FtpDataConnectionType.AutoActive(尤其内网穿透场景) 若目标路径含中文,需确认服务器FTP服务支持UTF-8(
client.Encoding = System.Text.Encoding.UTF8)
SSH.NET与FluentFTP选型:SFTP还是FTP over TLS?
名字都带“FTP”,但协议层完全不同:
SSH.NET走SFTP(SSH File Transfer Protocol,基于SSH通道),
FluentFTP主攻FTP/FTPS(FTP over TLS)。选错等于协议不匹配,必然失败。
判断依据看服务端暴露的端口和认证方式:
端口是22、认证用SSH密钥或Linux系统账号 → 必须用SSH.NET端口是21/990、要求TLS证书、用户名密码明文传输(但信道加密)→ 用
FluentFTP配
FtpEncryptionMode.Explicit端口是22但服务端实际跑的是Dropbear等轻量SSH,可能不支持SFTP子系统 → 用
SSH.NET的
SshClient先执行
RunCommand("sftp -V")验证
上传后校验文件完整性不能只比对大小
网络中断或缓冲区问题可能导致上传截断,但
Length碰巧一致。生产环境必须加哈希校验:
SSH.NET方案:上传后立刻用
SftpClient执行
ReadAllText("sha256sum /remote/file")(需服务端装coreutils);或更稳妥地,上传前本地算
SHA256.Create().ComputeHash(stream),上传后再用
SftpClient下载远程文件小片段+追加计算(避免全量下载)。
FluentFTP方案:用
client.GetChecksum("SHA256", "/remote/file")(仅限支持MD5/
SHA256扩展的FTP服务器,如ProFTPD + mod_digest)。
最易被忽略的一点:SFTP服务器若禁用
exec通道(如
ForceCommand internal-sftp),就无法运行
sha256sum,此时只能靠客户端本地重新下载并完整比对哈希——这意味着你得预留双倍存储和带宽。
