Skip to content

SFTP Logging Example

Christian Baker edited this page Oct 26, 2021 · 1 revision

FDOT has some experiences integrating with cubic controllers using SFTP. There are two components I added to the original UDOT solution to make SFTP work.

Step 0: Install SSH.NET from Nuget package, I am using the library written by Renci, which has 33.8M downloads. Step 1: Under MOE.Common application, add two SFTP handler functions: (you can name the function as you fit)

public void GetCubicFilesAsync() { // run the sftp fetch operation async Thread sftpFetch = new Thread(delegate () { // to-do: replace with common data access to access signal IP in batch from ATSPM DB string host = "signal IP"; string username = "SFTP signal user name"; string password = "SFTP signal password"; string remoteDirectory = "SFTP remote directory"; string localDirectory = "local path to store dat files from remote directory"; using (SftpClient sftp = new SftpClient(host, username, password)) { try { sftp.Connect();

                `var files = sftp.ListDirectory(remoteDirectory);`
                `var cubicFiles = files.Where(x => x.FullName.Contains(".dat")).ToList();`

                `//download current files, remove files from remote directory`
                `TransferCubicFiles(cubicFiles, localDirectory, sftp);`
                `sftp.Disconnect();`

            `}`
            `catch (Exception ex)`
            `{`
                `//to-do: add some custom error handling as fit `
                `throw ex;`
            `}`
        `}`
    `});`
    `sftpFetch.Start();`

}

private void TransferCubicFiles(List receivedFiles, string directory, SftpClient client) { var errorRepository = ApplicationEventRepositoryFactory.Create(); try { foreach (var ret in receivedFiles) { // FullName will include full path in sFTP // Name will just include the file name without path

            string fileName = ret.Name;
            string remoteFileName = ret.FullName;

            using (Stream fileStream = File.OpenWrite(Path.Combine(directory, fileName)))
            {
                Console.WriteLine("Downloading {0}", fileName);
                //copy file and get to local diretory
                client.DownloadFile(remoteFileName, fileStream);


                //remove file in remote directory
                Console.WriteLine("deleting {0} in sFTP instance", remoteFileName);
                //delete file in remote sFTP directory
                if (client.Exists(remoteFileName))
                {
                    client.DeleteFile(remoteFileName);
                }
            }

            string newFileName = RenameDatFiles(fileName, Signal.SignalID);
            File.Move(Path.Combine(directory, fileName), Path.Combine(directory, newFileName));
        }
    }
    catch (FTPException ex)
    {
        //capture if there is any sFTP related exception
        errorRepository.QuickAdd("sFTPFromControllers", "SignalFtp", "TransferCubicFiles", ApplicationEvent.SeverityLevels.Medium, Signal.SignalID + " @ " + Signal.IPAddress + " - " + ex.Message);
        Console.WriteLine(Signal.SignalID + " @ " + Signal.IPAddress + " - " + ex.Message);
    }
    catch (IOException ex)
    {
        //capture if there is any file IO exception
        errorRepository.QuickAdd("sFTPFromControllers", "SignalFtp", "TransferCubicFiles", ApplicationEvent.SeverityLevels.Medium, Signal.SignalID + " @ " + Signal.IPAddress + " - " + ex.Message);
        Console.WriteLine(Signal.SignalID + " @ " + Signal.IPAddress + " - " + ex.Message);
    }
}
Clone this wiki locally