中堅プログラマーの備忘録

忘れっぽくなってきたので備忘録として・・・

【C#.net】FtpWebRequestクラスを使ってFTPS接続でファイルをダウンロードする

1.条件

下記の条件で検証を行いました。
①サーバーはLinux
②パッシブモードでの接続
③制御コネクションのポート番号は【61234】
④自己署名証明書のため証明書の内容確認は行わない

とにかく暗号化通信したい場合を想定しています。


※今回使用したFTPSサーバーはこちら
www.chuken-engineer.com

2.証明書の確認を無視する

自己署名証明書を使ったサーバーなので証明書の確認をすると
【検証プロシージャによると、リモート証明書は無効です。】
というエラーが発生してしまいます。

これを回避するために
【ServicePointManager.ServerCertificateValidationCallback】
を使って証明書のチェックを無視するようにしています。

3.スクリプト

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FTPsample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // ダウンロード元のURI
            Uri u = new Uri("ftp://192.168.0.129:61234/test.txt");
            System.Net.FtpWebRequest ftpReq = (System.Net.FtpWebRequest)System.Net.WebRequest.Create(u);
            // ログインユーザー名とパスワードを設定
            ftpReq.Credentials = new System.Net.NetworkCredential("testuser", "testuser");
            ftpReq.Method = System.Net.WebRequestMethods.Ftp.DownloadFile;

            // 要求の完了後に接続を閉じる
            ftpReq.KeepAlive = false;
            // binalyモードで転送する
            ftpReq.UseBinary = true;
            // PASSIVEモード有効
            ftpReq.UsePassive = true;
            // SSL通信を有効にする
            ftpReq.EnableSsl = true;
            // 証明書の内容を確認しない為、強制的にtrueを返す
            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate (
            Object certsender, 
            X509Certificate certificate,
            X509Chain chain,
            SslPolicyErrors sslPolicyErrors) {
                return true;
            });

            try
            {
                System.Net.FtpWebResponse ftpRes = (System.Net.FtpWebResponse)ftpReq.GetResponse();
                // ダウンロード用のStreamを取得
                System.IO.Stream resStrm = ftpRes.GetResponseStream();
                // ファイル書き込みのFileStreamを作成
                System.IO.FileStream fs = new System.IO.FileStream("C:/test/test.txt", System.IO.FileMode.Create, System.IO.FileAccess.Write);
                // データ書き込み
                Byte[] buffer = new byte[1023];
                while (true)
                {
                    int readSize = resStrm.Read(buffer, 0, buffer.Length);
                    if (readSize == 0)
                    {
                        break;
                    }
                    fs.Write(buffer, 0, readSize);
                }
                fs.Close();
                resStrm.Close();
                ftpRes.Close();
            }
            catch (Exception ex)
            {
                // エラー処理
            }
        }
    }
}

4.動作確認

アプリケーションを起動すると
サーバーにある【test.txt】という名前のファイルを
FTPS通信で【C:/test/test.txt】にダウンロードするという動作になります。

動作については問題ありませんでした。

今回は自己署名証明書だったので【ServicePointManager】クラスを使って
信頼されていない証明書でも接続可能に出来ました。