是否有任何异步方式连接到 SFTP 服务器?

问题描述 投票:0回答:2

我正在开发一个 API,它接收消息并将它们以 .json 格式上传到 SFTP 服务器。但是,连接时间太长了,SFTP连接需要1秒多,太多了。 想知道有没有什么办法不用等那么久就可以连上服务器发送文件了

我想过保存文件,回答客户,然后用这个方法上传文件:

public async Task Upload(string localPath, string remotePath)
{
    await Task.Run(() =>
    {
        // upload code here
    });
}

但是,如果上传过程中出现异常,API可能已经向客户端响应了OK,导致无法通知客户端上传失败。

这是我目前用来上传文件的现有代码:

public void Upload(string localPath, string remotePath)
{
    try
    {
        using (var sftp = new SftpClient(...))
            {
                sftp.Connect(); // Very slow
                sftp.UploadFile(...);
                sftp.Disconnect();
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error Upload SFTPHandler");
    }
}

有人可以建议一个连接到 SFTP 服务器并发送文件而无需等待这么久的解决方案吗?

c# asynchronous sftp
2个回答
2
投票

您可以存储上传状态,并单独检查是否已上传。例如,您可以将状态缓存在

ConcurrentDictionary
中。然后客户端可以定期轮询上传状态。

假设你使用的是 SSH.Net 客户端,你也可以使用它的异步方法。

static ConcurrentDictionary<string, bool> _statuses = new();

[HttpPost]
public async Task UploadFile(string localPath, string remotePath)
{
    _statuses[remotePath] = false;
    Task.Run(() => Upload(localPath, remotePath));
}

private async Task Upload(string localPath, string remotePath)
{
    try
    {
        using var sftp = new SftpClient(...);
        sftp.ConnectAsync();
        await TaskFactory.FromAsync(
            (input, path, asyncCallback, state) =>
                sftp.BeginUploadFile(input, path, asyncCallback),
            sftp.EndUploadFile,
            ..., // some filestream
            remotePath,
            null);
        _statuses[remotePath] = true;
        sftp.Disconnect();
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error Upload SFTPHandler");
    }
}


[HttpPost]
public async Task<bool> IsUploaded(string remotePath)
{
    if (!_statuses.TryGetValue(remotePath, out var value))
    {
        // IIS was restarted.
        // check SFTP for finished upload.
        _statuses.Add(someStatus);
    }
    return value;
}

您可能需要考虑在 IIS 服务器重新启动时缓存状态的某种方式。


0
投票

但是,如果上传过程中出现异常,API可能已经向客户端响应了OK,导致无法通知客户端上传失败。

所有“即发即弃”的工作都是如此,这就是为什么它通常是错误的解决方案。

如果您绝对不能等待超过 1 秒(??对我来说听起来并不太不合理),那么您最好的选择是 基本分布式架构,如我的博客所述。基本的分布式架构有两部分,还有一个可选的第三部分(这听起来像你想要的):

  1. 持久队列。这是防止工作丢失所必需的。
  2. 处理队列的后台进程。
  3. 客户端轮询或通知,在工作完成时通知客户。
© www.soinside.com 2019 - 2024. All rights reserved.