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
似乎是一个很好的解决方案,但我不确定如何做到这一点。你太棒了。谢谢!