使用FluentFTP库实现FTP文件操作的类,包括删除文件、判断文件是否存在、读取文件、保存文件等操作。类中的方法都是异步的,使用了await和async关键字.
public interface IFileStore : IDisposable
{
Task<string> SaveAsync(string filefullname, Stream fileStream, bool isOverwrite = true);
Task<Stream> ReadAsync(string filefullname);
Task DeleteAsync(string filefullname);
Task<bool> ExistsAsync(string filefullname);
}
/// <summary>
/// ftp操作类
/// </summary>
public class FTPFileStore : IFileStore, IDisposable
{
private readonly ISession _Session;
private readonly ILogger _logger;
public FTPFileStore(ISession Session, ILogger logger)
{
_Session = Session;
_logger = logger;
}
private string GetFtpPath(string filefullName)
{
if (string.IsNullOrEmpty(filefullName))
{
throw new ArgumentNullException(nameof(filefullName));
}
if (filefullName.StartsWith("/"))
{
return $"/TID{_Session.GetTenantId()}/{filefullName}";
}
return $"/TID{_Session.GetTenantId()}{filefullName}";
}
private async Task<IFtpClient> GetFtpClientAsync()
{
var host = MSEApplication.GetConfigValue("FTP:Host").Trim();
var port = int.TryParse(MSEApplication.GetConfigValue("FTP:Port"), out var ftpPort) ? ftpPort : 21;
var userName = (MSEApplication.GetConfigValue("FTP:UserName") ?? string.Empty).Trim();
var password = (MSEApplication.GetConfigValue("FTP:Password") ?? string.Empty).Trim();
var ftpClient = new FtpClient(host, port, userName, password)
{
DataConnectionConnectTimeout = (int)TimeSpan.FromMinutes(2).TotalMilliseconds,
DataConnectionReadTimeout = (int)TimeSpan.FromMinutes(2).TotalMilliseconds,
ConnectTimeout = (int)TimeSpan.FromSeconds(30).TotalMilliseconds,
ReadTimeout = (int)TimeSpan.FromSeconds(30).TotalMilliseconds
};
if (!ftpClient.IsConnected)
{
await ftpClient.ConnectAsync();
}
return ftpClient;
}
public async Task DeleteAsync(string filefullName)
{
try
{
filefullName = GetFtpPath(filefullName);
using (var ftpClient = await GetFtpClientAsync())
{
await ftpClient.DeleteFileAsync(filefullName);
}
}
catch (Exception ex)
{
_logger.Error($"删除文件异常", ex);
throw;
}
}
public async Task<bool> ExistsAsync(string filefullName)
{
try
{
filefullName = GetFtpPath(filefullName);
using (var ftpClient = await GetFtpClientAsync())
{
return await ftpClient.FileExistsAsync(filefullName);
}
}
catch (Exception ex)
{
_logger.Error($"文件是否存在异常", ex);
throw;
}
}
public async Task<Stream> ReadAsync(string filefullName)
{
try
{
filefullName = GetFtpPath(filefullName);
using (var ftpClient = await GetFtpClientAsync())
{
var ms = new MemoryStream();
await ftpClient.DownloadStreamAsync(ms, filefullName);
ms.Position = 0L;
return ms;
}
}
catch (Exception ex)
{
_logger.Error($"文件加载异常", ex);
throw new BusinessException("文件加载异常!");
}
}
public async Task<string> SaveAsync(string filefullName, Stream fileStream, bool isOverwrite = true)
{
var sw = new Stopwatch();
sw.Start();
string ftpPath = GetFtpPath(filefullName);
try
{
fileStream.Position = 0L;
using (var ftpClient = await GetFtpClientAsync())
{
if ((await ftpClient.UploadStreamAsync(fileStream, ftpPath, FtpRemoteExists.Overwrite, createRemoteDir: true)) != FtpStatus.Success)
{
throw new BusinessException("文件保存失败!");
}
}
return filefullName;
}
catch (Exception ex)
{
_logger.Error("文件保存异常", ex);
throw;
}
finally
{
sw.Stop();
if (sw.ElapsedMilliseconds > 1000)
{
_logger.Debug("FTP上传文件:{filefullName}。时间:{sw.ElapsedMilliseconds}ms");
}
}
}
public void Dispose()
{
// no-op
}
}