Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

ASP.NET: Using SFTP/FTP in ASP.NET Projects

0.00/5 (No votes)
20 Jul 2020 1  
Using SFTP/FTP in ASP.NET projects
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
{
    /*winscp example
     * https://winscp.net/eng/docs/library_examples
     * Local Directory:         C:\DumpFiles\file.csv (C:\\DumpFiles\\file.csv)
     * Ftp Directory(WinScp):   /ArchiveFiles/file.csv
     */
    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 = "")
        {
            /*https://winscp.net/eng/docs/file_mask*/
            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",           /*for sftp use "Sftp" and for ftp use "Ftp"*/
    Host = "xx.xx.xx.xx",   /*host ip*/
    Port = 21,              /*ftp:21, sftp:22*/
    UserName = "xyz",
    Password = "abc"
};

IRemoteFileSystemContext remote = new FtpSftpFileContext(setting);

remote.Connect();                                       /*establish connection*/
remote.DownloadFile("C:\\1.txt", "/test/1.txt");        /*download file*/
remote.UploadFile("C:\\2.txt", "/test/2.txt");          /*upload upload file*/
List<string> files = remote.FileNames("/test/");        /*file names*/
files = remote.FileNames("/test/",  "1", ".txt");       /*search file with prefix, suffix*/

/*others*/
bool value;
value = remote.IsConnected();                           /*check connection done or not*/
value = remote.DirectoryExists("/test/");               /*check if directory exists or not*/
remote.CreateDirectoryIfNotExists("/test/lol/");        /*create directory*/
value = remote.FileExists("/files/test/1.txt");         /*check if file exists or not*/
remote.DeleteFileIfExists("/test/2.txt");               /*delete file*/
remote.Disconnect();                                    /*stop connection*/
remote.Dispose();                                       /*dispose*/

Future Works

Going to add them soon.

/*we don't have, but going to add some*/
/*get all directory name*/
/*download all files*/
/*upload all files*/

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

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here