You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SSH.NET连接本地SFTP服务器遇System.ObjectDisposedException错误求助

SSH.NET上传SFTP报错:Safe handle has been closed 问题修复

嘿,我看你用SSH.NET上传文件时碰到了System.ObjectDisposedException和Socket连接异常,好在命令行和FileZilla能正常连,说明SFTP服务本身没问题,问题大概率出在代码的资源管理和连接逻辑上。下面给你拆解几个关键问题点,以及修改后的代码:

核心问题分析

  • 缓冲区设置时机不对:你在每次上传文件时才设置client.BufferSize,频繁修改缓冲区会干扰底层Socket的资源状态,应该在连接建立后一次性设置好。
  • 路径拼接不规范:用+ "/" +拼接路径在跨平台环境(比如你用的Mono)容易出问题,换成Path.Combine更稳妥。
  • 冗余资源占用:代码里声明了SQLiteConnection但完全没用到,这会占用不必要的资源,建议清理掉。
  • 缺少异常处理:没有捕获连接或上传过程中的异常,一旦出错就直接抛出未处理异常,导致资源无法正常释放。

修改后的完整代码

public static void UploadToSFTP(List<string> selectedFileList)
{
    // 清理未使用的SQLiteConnection,减少资源占用
    string host = "myiphere";
    int port = 22;
    string username = "gth";
    string password = "1234";
    string remoteDir = @"/D/SFTP";

    // Using语句确保SftpClient自动释放资源,但内部也要做好异常处理
    using (var client = new SftpClient(host, port, username, password))
    {
        try
        {
            client.Connect();
            // 连接成功后立即设置缓冲区,不要在循环内重复操作
            client.BufferSize = 4 * 1024; 

            // 可选:先检查远程目录是否存在,不存在就创建
            if (!client.Exists(remoteDir))
            {
                client.CreateDirectory(remoteDir);
            }
            client.ChangeDirectory(remoteDir);

            foreach (var file in selectedFileList)
            {
                string localFilePath = Path.Combine(testPath, file);
                // 先检查本地文件是否存在,避免后续FileStream报错
                if (!File.Exists(localFilePath))
                {
                    Console.WriteLine($"跳过:本地文件不存在 -> {localFilePath}");
                    continue;
                }

                using (var fs = new FileStream(localFilePath, FileMode.Open, FileAccess.Read))
                {
                    string remoteFileName = Path.GetFileName(localFilePath);
                    Console.WriteLine($"开始上传:{remoteFileName}");
                    // 可选:添加上传进度回调,方便排查问题
                    client.UploadFile(fs, remoteFileName, (uploadedBytes) => 
                    {
                        Console.WriteLine($"进度:{uploadedBytes}/{fs.Length} bytes");
                    });
                }
            }

            // 显式断开连接,确保Socket资源正常释放
            client.Disconnect();
        }
        catch (SocketException ex)
        {
            Console.WriteLine($"连接异常:{ex.Message}");
            // 这里可以加重试逻辑,比如重试1-2次
        }
        catch (SftpException ex)
        {
            Console.WriteLine($"SFTP操作错误:{ex.Message}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"未知错误:{ex.Message}\n{ex.StackTrace}");
        }
    }
}

额外排查小贴士

  • 确认testPath变量是否正确初始化,指向本地文件的实际目录。
  • 如果你在Mono环境运行,检查SSH.NET版本是否适配当前Mono版本,尽量用最新稳定版。
  • 可以给连接加超时设置:client.ConnectionInfo.Timeout = TimeSpan.FromSeconds(30);,避免因超时导致Socket异常。
  • 查看SFTP服务器的日志,确认是否有连接被强制断开的记录(比如防火墙限制、用户权限问题)。

内容的提问来源于stack exchange,提问作者Goh Han

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:04:10