303 lines
12 KiB
C#
303 lines
12 KiB
C#
using KssSmaPlaLib.Commons;
|
|
using KssSmaPlaLib.Encryption;
|
|
using KssSmaPlaLib.IO.File;
|
|
using Renci.SshNet;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace KssSmaPlaLib.Communications
|
|
{
|
|
public class SftpUxer
|
|
{
|
|
public const string INIDIC_KEY_HOST = "Host";
|
|
public const string INIDIC_KEY_PORT = "Port";
|
|
public const string INIDIC_KEY_USERNAME = "UserName";
|
|
public const string INIDIC_KEY_PRIVATE_KEY_FILE_PATH = "PrivateKeyFilePath";
|
|
public const string INIDIC_KEY_PASS_PHRASE = "PassPhrase";
|
|
|
|
private readonly string _host;
|
|
private readonly int _port;
|
|
private readonly string _username;
|
|
private readonly string _privateKeyPath; // PuTTY形式でもOK
|
|
private readonly string _passPhrase;
|
|
|
|
public static bool TryCreateByDic(Dictionary<string, string> iniDic, out SftpUxer sftp, out string resultMessage)
|
|
{
|
|
sftp = null;
|
|
resultMessage = string.Empty;
|
|
|
|
// ホスト名
|
|
var host = DictionaryUxer.GetValueOrDefault(iniDic, INIDIC_KEY_HOST, string.Empty);
|
|
if (string.IsNullOrEmpty(host))
|
|
{
|
|
resultMessage = $"SFTPのホスト名が指定されていません。[キー:{INIDIC_KEY_HOST}]";
|
|
return false;
|
|
}
|
|
|
|
// ポート番号
|
|
var strPort = DictionaryUxer.GetValueOrDefault(iniDic, INIDIC_KEY_PORT, string.Empty);
|
|
if (int.TryParse(strPort, out var portNo) == false)
|
|
{
|
|
LoggerUxer.Error($"SFTPのポート番号が未指定または数値でありません。[キー:{INIDIC_KEY_PORT},ポート番号:{strPort}]");
|
|
return false;
|
|
}
|
|
|
|
// ユーザ名
|
|
var username = DictionaryUxer.GetValueOrDefault(iniDic, INIDIC_KEY_USERNAME, string.Empty);
|
|
if (string.IsNullOrEmpty(username))
|
|
{
|
|
LoggerUxer.Error($"SFTPのユーザ名が指定されていません。[キー:{INIDIC_KEY_USERNAME}]");
|
|
return false;
|
|
}
|
|
|
|
// プライベートキーファイルパス
|
|
var privateKeyPath = DictionaryUxer.GetValueOrDefault(iniDic, INIDIC_KEY_PRIVATE_KEY_FILE_PATH, string.Empty);
|
|
if (string.IsNullOrEmpty(privateKeyPath))
|
|
{
|
|
LoggerUxer.Error($"SFTPのプライベートキーファイルパスが指定されていません。[キー:{INIDIC_KEY_PRIVATE_KEY_FILE_PATH}]");
|
|
return false;
|
|
}
|
|
if (!File.Exists(privateKeyPath))
|
|
{
|
|
LoggerUxer.Error($"SFTPのプライベートキーファイルパスが存在しません。[キー:{INIDIC_KEY_PRIVATE_KEY_FILE_PATH},パス:{privateKeyPath}]");
|
|
return false;
|
|
}
|
|
|
|
// パスフレーズ
|
|
var passPhrase = DictionaryUxer.GetValueOrDefault(iniDic, INIDIC_KEY_PASS_PHRASE, string.Empty);
|
|
|
|
// ↓パスフレーズなしの場合もあり(必須としない)
|
|
//if (string.IsNullOrEmpty(passPhrase))
|
|
//{
|
|
// LoggerUxer.Error($"SFTPのパスフレーズが指定されていません。[キー:{INIDIC_KEY_PASS_PHRASE}]");
|
|
// return false;
|
|
//}
|
|
|
|
var passPhraseDec = string.Empty;
|
|
|
|
if (!string.IsNullOrEmpty(passPhrase))
|
|
{
|
|
// パスフレーズの復号化
|
|
if (!SimpleEncryptUxer.Decrypt(passPhrase, out passPhraseDec, out string messageForMe))
|
|
{
|
|
LoggerUxer.Error($"SFTPのパスフレーズ復号化で失敗しました。[キー:{INIDIC_KEY_PASS_PHRASE},エラー内容:{messageForMe}]");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// オブジェクト生成
|
|
sftp = new SftpUxer(host, portNo, username, privateKeyPath, passPhraseDec);
|
|
|
|
return true;
|
|
}
|
|
|
|
private SftpUxer(string host, int port, string username, string privateKeyPath, string passPhrase)
|
|
{
|
|
_host = host;
|
|
_port = port;
|
|
_username = username;
|
|
_privateKeyPath = privateKeyPath;
|
|
_passPhrase = passPhrase;
|
|
}
|
|
|
|
public bool TestConnect(out string resultMessage)
|
|
{
|
|
resultMessage = string.Empty;
|
|
try
|
|
{
|
|
PrivateKeyFile keyFile;
|
|
if(!string.IsNullOrEmpty(_passPhrase))
|
|
{
|
|
// パスフレーズあり
|
|
keyFile = new PrivateKeyFile(_privateKeyPath, _passPhrase);
|
|
}
|
|
else
|
|
{
|
|
// パスフレーズなし
|
|
keyFile = new PrivateKeyFile(_privateKeyPath);
|
|
}
|
|
|
|
var keyFiles = new[] { keyFile };
|
|
|
|
using (var client = new SftpClient(_host, _port, _username, keyFiles))
|
|
{
|
|
client.Connect();
|
|
client.Disconnect();
|
|
}
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
resultMessage = $"SFTPのテスト接続に失敗しました。[ホスト:{_host},ポート:{_port},ユーザ名:{_username},プライベートキーファイルパス:{_privateKeyPath},エラー内容:{ex.Message}]";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public bool Upload(List<string> filePathList, string remotePath, out string resultMessage)
|
|
{
|
|
resultMessage = string.Empty;
|
|
if (string.IsNullOrEmpty(remotePath)) remotePath = ".";
|
|
|
|
try
|
|
{
|
|
if (!remotePath.EndsWith("/")) remotePath += "/";
|
|
|
|
PrivateKeyFile keyFile;
|
|
if (!string.IsNullOrEmpty(_passPhrase))
|
|
{
|
|
keyFile = new PrivateKeyFile(_privateKeyPath, _passPhrase);
|
|
}
|
|
else
|
|
{
|
|
keyFile = new PrivateKeyFile(_privateKeyPath);
|
|
}
|
|
var keyFiles = new[] { keyFile };
|
|
|
|
using (var client = new SftpClient(_host, _port, _username, keyFiles))
|
|
{
|
|
client.Connect();
|
|
foreach (var filePath in filePathList)
|
|
{
|
|
using (var fileStream = new FileStream(filePath, FileMode.Open))
|
|
{
|
|
client.UploadFile(fileStream, remotePath + Path.GetFileName(filePath));
|
|
}
|
|
}
|
|
client.Disconnect();
|
|
}
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
resultMessage = $"SFTPのアップロードでエラーが発生しました。[ファイル:{string.Join(",", filePathList)},リモートパス:{remotePath},エラー内容:{ex.Message}]";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public bool Download(string remotePath, string localPath, out string resultMessage)
|
|
{
|
|
resultMessage = string.Empty;
|
|
try
|
|
{
|
|
var keyFile = new PrivateKeyFile(_privateKeyPath);
|
|
var keyFiles = new[] { keyFile };
|
|
|
|
using (var client = new SftpClient(_host, _port, _username, keyFiles))
|
|
{
|
|
client.Connect();
|
|
using (var fileStream = new FileStream(localPath, FileMode.Create))
|
|
{
|
|
client.DownloadFile(remotePath, fileStream);
|
|
}
|
|
client.Disconnect();
|
|
}
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
resultMessage = $"SFTPのダウンロード(Download)でエラーが発生しました。[エラー内容:{ex.Message}]";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public bool DownloadMatchingFiles(
|
|
string remoteDir,
|
|
string localDir,
|
|
out int downloadedFileCount,
|
|
out string resultMessage,
|
|
string pattern = "*.txt")
|
|
{
|
|
downloadedFileCount = 0;
|
|
resultMessage = string.Empty;
|
|
|
|
if (string.IsNullOrEmpty(remoteDir)) remoteDir = ".";
|
|
if (string.IsNullOrEmpty(localDir)) localDir = ".";
|
|
|
|
if (!Directory.Exists(localDir))
|
|
{
|
|
resultMessage = $"ダウンロード先のローカルフォルダが存在しません。[ローカルフォルダ:{localDir}]";
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
PrivateKeyFile keyFile;
|
|
if (!string.IsNullOrEmpty(_passPhrase))
|
|
{
|
|
keyFile = new PrivateKeyFile(_privateKeyPath, _passPhrase);
|
|
}
|
|
else
|
|
{
|
|
keyFile = new PrivateKeyFile(_privateKeyPath);
|
|
}
|
|
|
|
using (var client = new SftpClient(_host, _port, _username, keyFile))
|
|
{
|
|
client.Connect();
|
|
|
|
// リモートディレクトリ内のファイル一覧を取得
|
|
var files = client.ListDirectory(remoteDir)
|
|
.Where(f => !f.IsDirectory && StringUxer.WildcardMatch(f.Name, pattern));
|
|
|
|
foreach (var file in files)
|
|
{
|
|
string localPath = Path.Combine(localDir, file.Name);
|
|
using (var fs = new FileStream(localPath, FileMode.Create))
|
|
{
|
|
client.DownloadFile(file.FullName, fs);
|
|
Console.WriteLine($"1ファイルダウンロードしました。[ファイル名:{file.Name}]");
|
|
downloadedFileCount++;
|
|
}
|
|
}
|
|
client.Disconnect();
|
|
}
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
resultMessage = $"SFTPのダウンロード(DownloadMatchingFiles)でエラーが発生しました。[エラー内容:{ex.Message}]";
|
|
return false;
|
|
}
|
|
}
|
|
public bool DeleteMatchingFiles(
|
|
string remoteDir,
|
|
out int deletedFileCount,
|
|
out string resultMessage,
|
|
string pattern = "*.txt")
|
|
{
|
|
deletedFileCount = 0;
|
|
resultMessage = string.Empty;
|
|
try
|
|
{
|
|
var keyFile = new PrivateKeyFile(_privateKeyPath, _passPhrase);
|
|
using (var client = new SftpClient(_host, _port, _username, keyFile))
|
|
{
|
|
client.Connect();
|
|
|
|
// リモートディレクトリ内のファイル一覧を取得
|
|
var files = client.ListDirectory(remoteDir)
|
|
.Where(f => !f.IsDirectory && StringUxer.WildcardMatch(f.Name, pattern));
|
|
|
|
foreach (var file in files)
|
|
{
|
|
string remotePath = PathUxer.CombineUnixPath(remoteDir, file.Name);
|
|
client.DeleteFile(remotePath);
|
|
deletedFileCount++;
|
|
}
|
|
client.Disconnect();
|
|
}
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
resultMessage = $"SFTPのファイル削除でエラーが発生しました。[エラー内容:{ex.Message}]";
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|