user SSH.Net handle SFTP download and upload file
前言
個人工作上的程式碼備份,應該有未盡完善的部份,日後再隨時回來修改程式碼
實作
環境是.NET Framework 4.8
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
/*NuGet要先加入Renci.SshNet的參考 */
using Renci.SshNet;
using Renci.SshNet.Sftp;
namespace Console_MobilizeUploadFile.Utility
{
/*
文章參考:
[C#]SFTP (使用第三方套建 SSH.Net) - 類別庫為案例
https://hackmd.io/@RoyChen/SFTP_SSHNet
C# 使用 SSH.NET SFTP 上傳及下載範例
https://www.tpisoftware.com/tpu/articleDetails/2645
*/
public class MySshSftp
{
private SftpClient _sftp;
/// <summary>
/// SFTP 連接狀態
/// </summary>
public bool Connected { get { return _sftp.IsConnected; } }
/// <summary>
/// 建構子
/// </summary>
/// <param name="ip">IP</param>
/// <param name="port">端口</param>
/// <param name="account">id</param>
/// <param name="pwd">passwd</param>
public MySshSftp(string ip, string account, string pwd)
{
_sftp = new SftpClient(ip, port: 22, account, pwd);
}
/// <summary>
/// SFTP 連線
/// </summary>
/// <returns>true成功</returns>
public void Connect()
{
if (!Connected)
{
_sftp.Connect();
}
}
/// <summary>
/// SFTP 關閉
/// </summary>
public void Disconnect()
{
if (_sftp != null && Connected)
{
_sftp.Disconnect();
}
}
/// <summary>
/// 檢查指定的遠端目錄是否存在,如果不存在就遞迴創建。
/// </summary>
/// <param name="remoteDirectory"></param>
public void CreateDirectoryIfNotExists(string remoteDirectory)
{
var directories = remoteDirectory.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
string currentPath = "/";
_sftp.Connect();
foreach (var dir in directories)
{
currentPath = $"{currentPath}{dir}/";
if (_sftp.Exists(currentPath)==false)
{//不存在目錄
//建立目錄
_sftp.CreateDirectory(currentPath);
}
}//end foreach
_sftp.Disconnect();
}
/// <summary>
/// SFTP 上傳檔案
/// </summary>
/// <param name="localPath">本機檔案 (要上傳的檔案)</param>
/// <param name="uploadSftpFilePath">要上傳到 FTP 的路徑</param>
/// <param name="uploadFileName">指定新檔名 (若無,預設為原本的檔名)</param>
public void Upload(string localFilePath, string uploadSftpFilePath)
{
//uploadPath = setFullFileName(uploadPath, uploadFileName, localFilePath);
using (FileStream fs = System.IO.File.OpenRead(localFilePath))
{
Connect();
_sftp.UploadFile(fs, uploadSftpFilePath);
Disconnect();
}
}
public void Upload(byte[] file, string uploadSftpFilePath)
{
using (MemoryStream ms = new MemoryStream(file))
{
Connect();
_sftp.UploadFile(ms, uploadSftpFilePath);
Disconnect();
}
}
/// <summary>
/// SFTP 搬移檔案
/// </summary>
/// <param name="moveFile">要搬移的檔案</param>
/// <param name="newPath">要搬移到的新路徑</param>
/// <param name="newFileName">指定新檔名 (若無,預設為原本的檔名)</param>
/// <param name="isPosix">若新路徑已有相同檔案是否要覆蓋</param>
public void Move(string moveFile, string newPath, string newFileName = "", bool isPosix = false)
{
try
{
newPath = setFullFileName(newPath, newFileName, moveFile);
Connect();
_sftp.RenameFile(moveFile, newPath, isPosix);
Disconnect();
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// SFTP 下載檔案
/// </summary>
/// <param name="localPath">本機端路徑 (要下載到本機的路徑)</param>
/// <param name="sftpFilePath">遠端路徑</param>
/// <param name="localFileName">指定新檔名 (若無,預設為原本的檔名)</param>
public void Download(string localFilePath, string sftpFilePath)
{
//localPath = setFullFileName(localPath, localFileName, sftpFilePath);
Connect();
byte[] sftp_byt = _sftp.ReadAllBytes(sftpFilePath);
Disconnect();
System.IO.File.WriteAllBytes(localFilePath, sftp_byt);
}
/// <summary>
/// 讀取SFTP上的檔案為byte[]
/// </summary>
/// <param name="sftpFilePath"></param>
/// <returns></returns>
public byte[] ReadAllBytes(string sftpFilePath)
{
Connect();
byte[] sftp_byt = _sftp.ReadAllBytes(sftpFilePath);
Disconnect();
return sftp_byt;
}
/// <summary>
/// SFTP 刪除一個檔案
/// </summary>
/// <param name="deleteFilePath">要刪除的檔案</param>
public void Delete(string deleteFilePath)
{
Connect();
_sftp.Delete(deleteFilePath);
Disconnect();
}
/// <summary>
/// 遞迴刪除目錄&底下所有內容
/// </summary>
/// <param name="directoryPath"></param>
public void DeleteDirectoryRecursively(string directoryPath)
{
Connect();
// 列出目錄中的所有檔案和子目錄
var filesAndDirectories = _sftp.ListDirectory(directoryPath);
foreach (var entry in filesAndDirectories)
{
if (entry.Name == "." || entry.Name == "..")
continue;//略過
if (entry.IsDirectory)
{
// 遞迴刪除子目錄裡的檔案
DeleteDirectoryRecursively(entry.FullName);
}
else
{
// 刪除檔案
_sftp.Delete(entry.FullName);
}
}//end foreach
// 刪除當前目錄
_sftp.DeleteDirectory(directoryPath);
Disconnect();
}
/// <summary>
/// 取得 SFTP 路徑上的檔案與文件夾
/// </summary>
/// <param name="sftpPath">遠端路徑</param>
/// <param name="filenameExtension">附檔名</param>
/// <returns></returns>
public List<string> GetFileList(string sftpPath, string filenameExtension = "")
{
try
{
Connect();
IEnumerable<ISftpFile> files = _sftp.ListDirectory(sftpPath);
Disconnect();
if (string.IsNullOrEmpty(filenameExtension))
{
List<string> fileList = new List<string>();
foreach (var file in files)
{
string fileName = Path.GetFileName(file.FullName);
if (fileName == "." || fileName == "..")
{
continue;
}
fileList.Add(fileName);
}
return fileList;
}
else
{
return matchFileName(filenameExtension, files);
}
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 設定路徑與檔名
/// </summary>
/// <param name="path">路徑</param>
/// <param name="fileName">檔名</param>
/// <param name="sourceFullFileName">來源路徑與檔名</param>
private string setFullFileName(string path, string fileName, string sourceFullFileName)
{
fileName = string.IsNullOrEmpty(fileName) ? Path.GetFileName(sourceFullFileName) : fileName;
path += fileName;
return path;
}
/// <summary>
/// 配對檔名條件 (e.g. file_*.cs*)
/// </summary>
/// <param name="filenameExtension"></param>
/// <param name="files"></param>
private List<string> matchFileName(string filenameExtension, IEnumerable<ISftpFile> files)
{
string[] splitFileNameArry = filenameExtension.Split('.');
string filterFileName = "";
string filterExtension = splitFileNameArry[splitFileNameArry.Length - 1];
for (int i = 0; i < splitFileNameArry.Length - 1; i++)
{
filterFileName += splitFileNameArry[i] + ((splitFileNameArry.Length - 2 == i) ? "" : @"\.");
}
string fileNamePattern = "^" + filterFileName.Replace("*", ".*") + @"$";
string extensionPattern = @"\." + filterExtension.Replace("*", ".*") + @"$";
List<string> fileList = new List<string>();
foreach (var file in files)
{
string fileName = Path.GetFileNameWithoutExtension(file.FullName);
string extension = Path.GetExtension(file.FullName);
bool isMatchFileName = Regex.IsMatch(fileName, fileNamePattern);
bool isMatchExtension = Regex.IsMatch(extension, extensionPattern);
if (isMatchFileName && isMatchExtension)
{
fileList.Add(fileName + extension);
}
}
return fileList;
}
}
}