处理返回流的连接

时间:2015-10-14 21:25:21

标签: c# asp.net asp.net-mvc

我正在使用Renci.SshNet.Sftp建立与SFTP服务器的连接。连接后,我将服务器上找到的SftpFileStream文件返回到我的控制器的动作。控制器实际上将SftpFileStream的读者发送到一个服务方法,该方法解析流并根据信息执行所需的操作。

这是问题......

在实例化新SftpClient时,应使用using关键字确保连接已被丢弃。但是,如果我这样做,那么SftpClient会在解析文件之前被释放。为了解决这个问题,我删除了using语句,一切都很顺利。但后来我无法处置SftpClient。那该怎么办?

这是一些代码......

连接服务:

public class SFTPConnectionService
{
    public SftpFileStream GetRemoteFile(string filename)
    {
        // Server credentials
        var host = "host";
        var port = 22;
        var username = "username";
        var password = "password";

        var sftp = new SftpClient(host, port, username, password);

        // Connect to the SFTP server
        sftp.Connect();

        // Read the file in question
        var file = sftp.OpenRead(filename);

        return file;
    }
}

控制器:

public class RemoteFileController : Controller
{
    public ActionResult SFTP()
    {
        var sftpService = new SFTPConnectionService();

        using (var reader = new StreamReader(sftpService.GetRemoteFile(@"path/filename.txt")))
        {
            // Do whatever with the file

            return View("View", ViewModel);
        }
    }
}

所以我在using周围使用StreamReader块来读取文件,这样就会被处理掉,但仍然会留下需要处理的SftpClient

我曾考虑将SftpFileStream复制到另一个流,并将其返回以便将SftpClient包裹在using块中,但这似乎已经是一个坏主意了,而且我也不知道文件有多大,所以我真的想从SFTP服务器中流式传输它,而不是将它全部复制到内存中。

我该如何处理这种情况?

1 个答案:

答案 0 :(得分:1)

  

我真的想从SFTP服务器流式传输而不是将其全部复制到内存

当它被添加到ViewModel时,无论如何都会进入内存。这里有几个选项:

  • 将流包装在实现IDisposable的类中,并负责处理流客户端。
  • 不返回流,而是从中返回数据。然后你可以一起处理流和客户端。

如果您想SFTPConnectionService实施IDisposable,那么您可以这样做:

  • SFTPConnectionServiceStreamReader
  • 添加类属性
  • Dispose方法添加SFTPConnectionService方法,在每个方法上调用Dispose

这样的事情:

public class SFTPConnectionService : IDisposable
{

    private SftpClient sftp;
    private SftpFileStream file;

    public SftpFileStream GetRemoteFile(string filename)
    {
        // Server credentials
        var host = "host";
        var port = 22;
        var username = "username";
        var password = "password";

        sftp = new SftpClient(host, port, username, password);

        // Connect to the SFTP server
        sftp.Connect();

        // Read the file in question
        file = sftp.OpenRead(filename);

        return file;
    }

    // Recommended implementation of IDisposable:
    public void Dispose()
    {
        Dispose(true);

        // Use SupressFinalize in case a subclass 
        // of this type implements a finalizer.
        GC.SuppressFinalize(this);   
    }
    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing) 
            {
                if(sftp != null)
                     sftp.Dispose();
                if(file != null)
                     file.Dispose();
            }

            // Indicate that the instance has been disposed.
            _disposed = true;   
        }
    }
}

您的通话代码将是

using(var sftpService = new SFTPConnectionService())
using(var reader = new StreamReader(sftpService.GetRemoteFile(@"path/filename.txt")))
{
        // Do whatever with the file

        return View("View", ViewModel);
}