Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 处理返回流的连接_C#_Asp.net_Asp.net Mvc - Fatal编程技术网

C# 处理返回流的连接

C# 处理返回流的连接,c#,asp.net,asp.net-mvc,C#,Asp.net,Asp.net Mvc,我正在使用Renci.SshNet.Sftp与Sftp服务器建立连接。连接后,我会将服务器上找到的文件的SftpFileStream返回给控制器的操作。控制器实际上将SftpFileStream的读取器发送给服务方法,该服务方法解析流,并根据需要处理信息 问题是 在实例化新的SftpClient时,应使用using关键字以确保连接已断开。但是,如果我这样做,那么在解析文件之前,SftpClient就会被释放。为了解决这个问题,我使用语句删除了,一切正常。但是我没有办法处理SftpClient。那

我正在使用
Renci.SshNet.Sftp
与Sftp服务器建立连接。连接后,我会将服务器上找到的文件的
SftpFileStream
返回给控制器的操作。控制器实际上将
SftpFileStream
的读取器发送给服务方法,该服务方法解析流,并根据需要处理信息

问题是

在实例化新的
SftpClient
时,应使用
using
关键字以确保连接已断开。但是,如果我这样做,那么在解析文件之前,
SftpClient
就会被释放。为了解决这个问题,我使用语句删除了
,一切正常。但是我没有办法处理
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);
        }
    }
}
因此,我在读取文件的
StreamReader
周围使用了
using
块,这样就可以处理该文件,但仍然会留下需要处理的
SftpClient

我曾想过将
SftpFileStream
复制到另一个流,然后返回,这样我就可以使用
块将
SftpClient
包装到
中,但这似乎已经是个坏主意,而且我也不知道文件有多大,因此,我真的希望从SFTP服务器流式传输它,而不是将其全部复制到内存中

我如何处理这种情况

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

当它被添加到ViewModel中时,所有的内容都会进入内存。这里有几个选项:

  • 将流包装在一个类中,该类实现了
    IDisposable
    ,并负责处理流和客户端
  • 不要返回流,而是从中返回数据。然后您可以一起处理流和客户端
如果您想使
SFTPConnectionService
实现
IDisposable
,则可以执行以下操作:

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;   
        }
    }
}
  • SFTPConnectionService
    StreamReader
  • 将一个
    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);
}

拥有
SFTPConnectionService
实现
IDisposable
。如果
SFTPConnectionService
实现
IDisposable
,我将如何处理从类的方法中建立的连接?控制器中的
StreamReader
实际上会将流传递到另一个类中的另一个方法。该方法逐行解析文件,只提取所需内容,并以ViewModel的形式返回控制器。根据您和Jasen的评论,在
SFTPConnectionService
中实现
IDisposable
似乎是一个很好的解决方案,但我不确定如何做到这一点。你太棒了。谢谢!