C# SFTP SSH.NET

C# 使用 SSH.NET SFTP 上傳及下載範例

蔡雅勤 2021/12/22 18:38:18
13165

 

一、前言

近年來資安議題越來越重要,過去C# 使用檔案傳輸協定 FTP 上傳及下載的相關程式,也應該升級為SFTP安全文件傳送協議。 C# 如何 SFTP 下載上傳呢?目前 .NET 已有不少現成的 SFTP 客戶端程式庫,以下範例使用開源專案 SSH.NET,它支援範圍很廣泛 。

Framework Support

  • .NET Framework 3.5
  • .NET Framework 4.0 (and higher)
  • .NET Standard 1.3
  • .NET Standard 2.0
  • Silverlight 4
  • Silverlight 5
  • Windows Phone 7.1
  • Windows Phone 8.0
  • Universal Windows Platform 10

 

 

二、環境準備

本範例安裝 Visual Studio 2020

 

 

三、安裝SSH.NET

使用NuGet管理套件安裝SSH.NET

 

透過NuGet安裝成功後,可以在參考裡看到SSH.NET

 

四、範例程式

透過建立主控台應用程式專案來實作,包含SFTP的登入連接、建立資料夾、上傳檔案、下載檔案、將檔案搬移到其他資料夾、刪除檔案、刪除目錄、顯示目錄下資料等範例。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Renci.SshNet;
using Renci.SshNet.Sftp;

namespace SFTPDemo
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //此範例直接輸入SFTP Server的IP、帳號、密碼
            //正式實務上應該將帳號密碼加密放在設定檔內
            using (var sftp = new SftpClient("10.211.55.19", "tester", "password"))
            {
                //SFTP Server連線
                sftp.Connect();

                //顯示SFTP Server 資料夾目錄
                Action<SftpFile> ShowDirOrFile = (item) => {
                    if (item.IsDirectory)
                        Console.WriteLine($"[{item.Name}]");
                    else
                        Console.WriteLine($"{item.Name:-32} {item.Length,8:N0} bytes");
                };

                Action<string> DirList = (path) =>
                {
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine($"顯示 {path} 目錄: ");
                    var list = sftp.ListDirectory(path)
                        //忽略 . 及 .. 目錄
                        .Where(o => !".,..".Split(',').Contains(o.Name))
                        .ToList();
                    if (list.Any())
                        list.ForEach(ShowDirOrFile);
                    else
                    {
                        Console.ForegroundColor = ConsoleColor.DarkYellow;
                        Console.WriteLine("沒有檔案.");
                    }
                    Console.WriteLine();
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.WriteLine();

                };

                //目前工作的資料夾
                var working_directory = sftp.WorkingDirectory;
                DirList(working_directory);

                //建立資料夾
                var folderA = $"/Test_"+DateTime.Now.ToString("yyyyMMdd")+"_A";
                var folderB = $"/Test_" + DateTime.Now.ToString("yyyyMMdd") + "_B";
                if (!sftp.Exists(folderA)) //驗證資料夾是否存在
                {
                    Console.WriteLine("建立資料夾" + folderA);
                    sftp.CreateDirectory(folderA);
                }
                if (!sftp.Exists(folderB))
                {

                    Console.WriteLine("建立資料夾" + folderB);
                    sftp.CreateDirectory(folderB);
                }

                DirList("/");

                //下載檔案
                Console.WriteLine("下載檔案DownTest.txt");
                var WorkPath = $"C:\\Users\\yachyn\\Desktop\\SFTP";
                var destFilePath = Path.Combine(WorkPath, "DownTest_"+ DateTime.Now.ToString("yyyymmddhhmmss") +".txt");
                using (var file = new FileStream(destFilePath, FileMode.Create, FileAccess.Write))
                {
                    sftp.DownloadFile($"/DownTest.txt", file);
                }
                Console.WriteLine("");

                //上傳檔案
                Console.WriteLine($"上傳檔案Uploadtest.txt到{folderA}");
                sftp.ChangeDirectory(folderA); //更換工作資料夾
                var sourcefile = "C:\\Users\\yachyn\\Desktop\\SFTP\\Uploadtest.txt";
                using (FileStream fs = new FileStream(sourcefile, FileMode.Open, FileAccess.Read))
                {
                    sftp.BufferSize = 4 * 1024;
                    sftp.UploadFile(fs, Path.GetFileName(sourcefile));
                }
                DirList(folderA);

                //搬移檔案
                Console.WriteLine($"從{folderA}搬移檔案到{folderB}");
                if (!sftp.Exists($"/{folderB}/Uploadtest.txt"))
                {
                    sftp.RenameFile($"/{folderA}/Uploadtest.txt", $"/{folderB}/Uploadtest.txt");
                }

                DirList(folderA);
                DirList(folderB);

                //刪除檔案
                Console.WriteLine("刪除檔案DeleteTest.txt");
                sftp.DeleteFile($"/DeleteTest.txt");

                //刪除資料夾
                Console.WriteLine($"刪除資料夾TestFolder");
                sftp.DeleteDirectory($"/TestFolder");

                DirList("/");
            }

            Console.Read();
        }
    }
}

 

 

五、範例程式執行測試

透過FileZilla軟體連接到SFTP站台,可看到目前站台底下的目錄及檔案。

有一個TestFolder資料夾及DeleteTest.txt、DownTest.txt兩個檔案。

 

執行程式進行測試,測試成功!

 

再重新查看SFTP站台,已變成有兩個資料夾及只剩下DownTest.txt一個檔案。

 

下載的DownTest.txt檔案,也有正確下載!

 

 

六、結語

透過本範例,應該可以涵蓋大部分SFTP操作,希望有對同樣需求的人有點幫助。另外https://www.sftp.net/ 這個網站收集很多SFTP的相關資訊,學習使用SFTP前,可以先到這網站瀏覽學習一下,非常有幫助。

 

 

七、參考資料

https://github.com/sshnet/SSH.NET

https://www.sftp.net/

https://blog.darkthread.net/blog/sftp-with-csharp/

https://www.coder.work/article/6432868

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

蔡雅勤