我正在使用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服务器中流式传输它,而不是将它全部复制到内存中。
我该如何处理这种情况?
答案 0 :(得分:1)
我真的想从SFTP服务器流式传输而不是将其全部复制到内存
当它被添加到ViewModel时,无论如何都会进入内存。这里有几个选项:
IDisposable
的类中,并负责处理流和客户端。如果您想SFTPConnectionService
实施IDisposable
,那么您可以这样做:
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);
}