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

SFTP大文件上传时服务器断开连接求助(Azure函数+C#)

解决SFTP大文件上传被服务器断开连接的问题

问题背景

用C#开发的Azure Function App,通过SSH.NET 2020.0.1包上传文件到SFTP服务器。小文件上传正常,但3-5GB的大文件上传时,服务器会主动断开连接,报错:

Sftp file transfer failed. File:Import/test.zip Error: Connection was closed by the server.

原代码:

public async Task UploadFile(BlockBlobClient client, string destination)
{
    try
    {
        using var inputStream = await client.OpenReadAsync();
        inputStream.Position = 0;
        if (!_sftpClient.IsConnected)
        {
            _sftpClient.Connect();
        }
        _sftpClient.UploadFile(inputStream, destination);
    }
    catch (Exception ex)
    {
        _log.LogError("transfer failed {msg}",ex.Message);
        
    }
    finally
    {
     _sftpClient.Disconnect();
    }
}

解决方案

1. 改用分块上传(核心修复)

SSH.NET默认的UploadFile是一次性传输整文件,大文件传输耗时太长,容易触发服务器超时。改成分块传输,把文件拆成小块发送,还能避免连接长时间闲置。

修改后的代码:

public async Task UploadFile(BlockBlobClient client, string destination)
{
    try
    {
        using var inputStream = await client.OpenReadAsync();
        inputStream.Position = 0;
        
        if (!_sftpClient.IsConnected)
        {
            _sftpClient.Connect();
        }

        // 设置分块大小(示例为10MB,可根据服务器配置调整)
        var bufferSize = 10 * 1024 * 1024;
        using var uploadStream = _sftpClient.Create(destination);
        byte[] buffer = new byte[bufferSize];
        int bytesRead;
        
        while ((bytesRead = await inputStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
        {
            await uploadStream.WriteAsync(buffer, 0, bytesRead);
            // 每块传输后刷新,确保数据及时发送,避免连接闲置
            uploadStream.Flush();
        }
    }
    catch (Exception ex)
    {
        _log.LogError("transfer failed {msg}", ex.Message);
        _log.LogError("Full exception: {ex}", ex); // 建议记录完整异常栈,方便排查
    }
    finally
    {
        if (_sftpClient.IsConnected)
        {
            _sftpClient.Disconnect();
        }
    }
}

2. 开启SSH连接心跳

设置KeepAlive间隔,防止服务器因为长时间无数据交互断开连接。初始化SftpClient时添加配置:

// 示例:每30秒发送一次心跳包
_sftpClient = new SftpClient(host, port, username, password);
_sftpClient.KeepAliveInterval = TimeSpan.FromSeconds(30);

3. 调整Azure Function超时时间

Azure Function消费计划默认超时5分钟,大文件上传肯定不够用。在host.json里修改超时配置:

{
  "functionTimeout": "02:00:00" // 设置为2小时,根据实际传输时长调整
}

注意:消费计划最大超时是10分钟,如果需要更长时间,得切换到高级计划或专用计划。

4. 排查SFTP服务器限制

联系SFTP服务器管理员确认:

  • 是否有单个文件大小限制
  • 连接超时时间设置
  • 是否允许分块传输大文件

5. 优化Blob读取方式(可选)

直接读取Blob流可能有内存压力,建议先把Blob下载到Azure Function的临时存储,再上传到SFTP:

public async Task UploadFile(BlockBlobClient client, string destination)
{
    try
    {
        // 下载到临时文件
        var tempFilePath = Path.GetTempFileName();
        await client.DownloadToAsync(tempFilePath);
        
        if (!_sftpClient.IsConnected)
        {
            _sftpClient.Connect();
        }

        using var fileStream = new FileStream(tempFilePath, FileMode.Open, FileAccess.Read);
        var bufferSize = 10 * 1024 * 1024;
        using var uploadStream = _sftpClient.Create(destination);
        byte[] buffer = new byte[bufferSize];
        int bytesRead;
        
        while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
        {
            await uploadStream.WriteAsync(buffer, 0, bytesRead);
            uploadStream.Flush();
        }
        
        // 删除临时文件
        File.Delete(tempFilePath);
    }
    catch (Exception ex)
    {
        _log.LogError("transfer failed {msg}", ex.Message);
        _log.LogError("Full exception: {ex}", ex);
    }
    finally
    {
        if (_sftpClient.IsConnected)
        {
            _sftpClient.Disconnect();
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 20:06:22