SSH.NET上传SFTP文件失败多因服务端配置问题:未启用SFTP子系统、防火墙拦截22端口、认证信息缺失或路径越界;FluentFTP大文件上传需流式处理防内存溢出;选型须据端口与协议匹配——22端口用SSH.NET,21/990端口用FluentFTP;完整性校验须避开exec限制,优先本地计算哈希比对。

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((如有口令),导致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,此时只能靠客户端本地重新下载并完整比对哈希——这意味着你得预留双倍存储和带宽。








