---
# System prepended metadata

title: Alex FTPS
tags: [C#, FTP, FTPS]

---

# Alex FTPS

因為原生.net 的FTP lib 不支援Implicit模式的FTPS
所以一定要用第三方來做

1. FluentFTPS
2. Alex FTPS

只有這兩個是自由軟體

Alex很久沒維護了(2015)，
FluentFTPS Implicit有錯誤的問題，也沒解決

所以選Alex，Alex的說明資源不多，大致研究如下
ESSLSupportMode是選Implicit
```csharp=
using (FTPSClient client = new FTPSClient())
                {
                    NetworkCredential networkCredential = new NetworkCredential()
                    {
                        UserName = "user",
                        Password = "pass"
                    };
 client.Connect("123.234.345.456", networkCredential, ESSLSupportMode.Implicit,
                        new RemoteCertificateValidationCallback(ValidateTestServerCertificate));
```


前面Credential都好懂，但**RemoteCertificateValidationCallback**
要另外處理，加上

```csharp=
 private static bool ValidateTestServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }
```

用來接收所有Certification證書，很多FTPS 的X509證書都是自簽的，變成說要Pass過這個證書檢查才能用

```csharp=
client.SetCurrentDirectory("dictionary");
client.StartKeepAlive();
```
不多說，好懂

再來是PutFile

```csharp=
client.PutFile("localfilepath", "remotefilepath", new FileTransferCallback(TransferCallbackFunction));
```
最主要說明這個**FileTransferCallback**

他是Delegate Function，

代表它把方法當成參數傳送，也就是
Server的 FileTransferCallback 回傳值，一定要用一個Function來接，因此就寫一個一樣的Function
```csharp=
private static void TransferCallbackFunction(FTPSClient sender, ETransferActions action, string localObjectName, string remoteObjectName, ulong fileTransmittedBytes, ulong? fileTransferSize, ref bool cancel)
        {
            switch (action)
            {
                case ETransferActions.FileUploaded:
                    OnFileTransferCompleted(fileTransmittedBytes, fileTransferSize, localObjectName);
                    break;
            }
        }
```

收到傳回來得資料，可以在Argument欄位看到會有甚麼資料回來，
主要Action比較重要，他定義了一些傳輸動作，像是 
1. 上傳完成
2. 上傳狀態
3. 下載狀態
4. 下載完成
5. 目錄建立
6. 目錄移除

等等
我們只要對這些Action做處理就好了，所以再加上
```csharp=
private static void OnFileTransferCompleted(ulong fileTransmittedBytes, ulong? fileTransferSize, string localObjectName)
        {
            if (fileTransferSize != null)
            {
                if (fileTransferSize != fileTransmittedBytes)
                {
                    TransferResult = $"WARNING: transfer file {localObjectName} size ({fileTransferSize.Value}) differs from the transferred bytes count ({fileTransmittedBytes}) At {string.Format("{0:yyyyMMddHHmmss}", DateTime.Now)} ";
                    return;
                }
            }
            TransferResult = "Success";
        }
```

TransferResult 這個是全域的String，拿來當作狀態紀錄
比較好在其他Function內做使用

參考資料:
[Alex FTPSv2](https://github.com/luck02/FTPSClient/tree/f2a9cef0daa82f70747df52a41a918a4712f88b8)
[Delegate Function](https://eric0806.blogspot.com/2015/01/dotnet-delegate-usage.html)


###### tags: `C#`,`FTPS`,`FTP`