This post demonstrates how to do SFTP/FTP interactions and operations in ASP.NET projects.
Background
In this article, we will check FTP/SFTP usages in ASP.NET projects. We are going to create an FTP/SFTP client class to connect and do operations on FTP/SFTP systems.
The operation includes:
- Connecting/disconnecting with the server
- Uploading/downloading files
- Checking files/directories
- Creating/deleting files/directories
- And others
SFTP/FTP
Here are some common Interfaces to create some adapter classes for SFTP and FTP clients.
using System;
using System.Collections.Generic;
namespace DotNetFtpSftp
{
public interface IFileSystem
{
bool FileExists(string filePath);
bool DirectoryExists(string directoryPath);
void CreateDirectoryIfNotExists(string directoryPath);
void DeleteFileIfExists(string filePath);
}
public interface IRemoteFileSystemContext : IFileSystem, IDisposable
{
bool IsConnected();
void Connect();
void Disconnect();
List<string> FileNames(string directory);
List<string> FileNames(string directory, string filePrefix,
string fileSuffixOrExtension = "");
void UploadFile(string localFilePath, string remoteFilePath);
void DownloadFile(string localFilePath, string remoteFilePath);
}
}
For SFTP/FTP works, we are going to use WinSCP. We can add the below code to our packages.config file or install it using NuGet.
<packages>
<package id="WinSCP" version="5.17.6" targetFramework="net45" />
</packages>
Let's create the adapter
class by implementing the interface.
using System;
using System.Collections.Generic;
using System.Linq;
using WinSCP;
namespace DotNetFtpSftp
{
public class FtpSftpFileContext : IRemoteFileSystemContext
{
public SessionOptions SessionOptions { get; }
private Session _session;
public FtpSftpFileContext(RemoteSystemSetting setting)
{
string protocolType = setting.Type;
SessionOptions = new SessionOptions
{
HostName = setting.Host,
UserName = setting.UserName,
Password = setting.Password,
PortNumber = setting.Port,
Protocol = (Protocol) Enum.Parse(typeof(Protocol), protocolType),
};
if (new List<Protocol>(){ Protocol.Sftp }.Contains(SessionOptions.Protocol))
{
SessionOptions.GiveUpSecurityAndAcceptAnySshHostKey = true;
}
}
public void Connect()
{
_session = new Session();
_session.Open(SessionOptions);
}
public List<string> FileNames(string directory)
{
var files = _session.EnumerateRemoteFiles
(directory, "", EnumerationOptions.None).ToList();
return files.Select(x => x.Name).ToList();
}
public List<string> FileNames
(string directory, string filePrefix, string fileSuffixOrExtension = "")
{
string mask = filePrefix + "*" + fileSuffixOrExtension;
var files = _session.EnumerateRemoteFiles
(directory, mask, EnumerationOptions.None).ToList();
return files.Select(x => x.Name).ToList();
}
public bool IsConnected()
{
var value = _session == null ? false : _session.Opened;
return value;
}
public void Disconnect()
{
_session.Close();
}
public void UploadFile(string localFilePath, string remoteFilePath)
{
TransferOptions transferOptions = new TransferOptions();
transferOptions.TransferMode = TransferMode.Binary;
TransferOperationResult transferResult =
_session.PutFiles(localFilePath, remoteFilePath, false, transferOptions);
transferResult.Check();
}
public void DownloadFile(string localFilePath, string remoteFilePath)
{
TransferOptions transferOptions = new TransferOptions();
transferOptions.TransferMode = TransferMode.Binary;
TransferOperationResult transferResult =
_session.GetFiles(remoteFilePath, localFilePath, false, transferOptions);
transferResult.Check();
}
public bool FileExists(string filePath)
{
bool has = _session.FileExists(filePath);
return has;
}
public bool DirectoryExists(string directoryPath)
{
bool has = _session.FileExists(directoryPath);
return has;
}
public void CreateDirectoryIfNotExists(string directoryPath)
{
if (!DirectoryExists(directoryPath))
{
_session.CreateDirectory(directoryPath);
}
}
public void DeleteFileIfExists(string filePath)
{
if (DirectoryExists(filePath))
{
_session.RemoveFile(filePath);
}
}
public void Dispose()
{
if (_session != null)
{
_session.Dispose();
}
}
}
}
Using the Code
Here are the uses of the SFTP/FTP adapter classes:
RemoteSystemSetting setting = new RemoteSystemSetting()
{
Type = "Ftp",
Host = "xx.xx.xx.xx",
Port = 21,
UserName = "xyz",
Password = "abc"
};
IRemoteFileSystemContext remote = new FtpSftpFileContext(setting);
remote.Connect();
remote.DownloadFile("C:\\1.txt", "/test/1.txt");
remote.UploadFile("C:\\2.txt", "/test/2.txt");
List<string> files = remote.FileNames("/test/");
files = remote.FileNames("/test/", "1", ".txt");
bool value;
value = remote.IsConnected();
value = remote.DirectoryExists("/test/");
remote.CreateDirectoryIfNotExists("/test/lol/");
value = remote.FileExists("/files/test/1.txt");
remote.DeleteFileIfExists("/test/2.txt");
remote.Disconnect();
remote.Dispose();
Future Works
Going to add them soon.
About the Source Code
It a Visual Studio 2017 solution and .NET Framework 4.5 projects.
DotNetFtpSftp
: console app
The code may throw unexpected errors for untested inputs. If any, just let me know.
How to Do the Same for ASP.NET CORE?
History
- 20th July, 2020: Initial version