C# 使用 SSH.NET SFTP 上傳及下載範例
一、前言
近年來資安議題越來越重要,過去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://blog.darkthread.net/blog/sftp-with-csharp/
https://www.coder.work/article/6432868