DockerでFTPサーバを起動してC#でファイル転送を行う
はじめに
前回はDockerでSQL Serverを起動して開発に利用しました。
knkomko.hatenablog.com
今回はFTPサーバを使うため、前回と同様にDockerを利用していきます。
DockerでPure-FTPdを起動してC#によりファイル転送を行います。
yml形式のファイルとC#のソースコードはこちらです。
github.com
開発環境
・Widnows10 Pro
・Docker Engine Community Version 20.10.5
使用するファイル
C:\DOCKER\PURE-FTP\ │ docker-compose.yml │ ├─ etc\ │ └─ home\
docker-compose.yml
FTPでファイルをアップロードすると ./home ディレクトリに保存されます。
version: '3' services: ftp-server: image: stilliard/pure-ftpd:hardened container_name: ftp-server ports: - "21:21" - "30000-30009:30000-30009" volumes: - ./home:/home/ftpusers - ./etc:/etc/ssl/private environment: - PUBLICHOST=localhost - FTP_USER_NAME=xuser - FTP_USER_PASS=xpass - FTP_USER_HOME=/home/ftpusers - ADDED_FLAGS="--tls=2"
FTPサーバの起動
yml形式のファイルと同じディレクトリで compose upを実行します。
$docker compose up -d --build
container ls で起動しているコンテナにFTPサーバが表示されることを確認します。
$docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d31b413c7a11 stilliard/pure-ftpd:hardened "/bin/sh -c '/run.sh…" 54 seconds ago Up 46 seconds 0.0.0.0:21->21/tcp, 0.0.0.0:30000-30009->30000-30009/tcp ftp-server
stop <コンテナ名> で起動しているコンテナを停止できます。
$docker stop ftp-server
start <コンテナ名> で停止しているコンテナを起動できます。
$docker start ftp-server
FTPサーバの確認
Windows10の場合になります。
エクスプローラーからFTPサーバに接続ができる事を確認します。
ftp://localhost/
サインオンの画面ではアカウント情報を入力します。
[Log On]ボタンを押下するとFTPサーバに接続できます。
ユーザー名:xuser パスワード:xpass
C#でファイル転送
FTPサーバーにファイル転送を行うサンプルになります。
サンプルの作成にあたって参考にした公式ドキュメントです。
docs.microsoft.com
ファイルの転送の方法は2ステップです。
ステップ1でFTPサーバにログオンします。
ログオンに成功するとファイル転送を行うStreamが取得できます。
// Get the object used to communicate with the server. FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://" + TextHost.Text + "/" + ListBoxDirectory.SelectedItem.ToString()); request.Method = WebRequestMethods.Ftp.DownloadFile; // FTP user logon. request.Credentials = new NetworkCredential(TextUserName.Text, TextPassword.Text);
ステップ2でファイルの転送を行います。
ダウンロードになりますが、FileStreamを使用してFTPサーバにあるファイルのバイナリを1024バイトごと読み込んで、ローカルのファイルに書き込んでいます。
using (FileStream fs = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + @"\Downloads\" + ListBoxDirectory.SelectedItem.ToString(), FileMode.CreateNew, FileAccess.Write)) using (Stream responseStream = response.GetResponseStream()) { byte[] buffer = new byte[1024]; while (true) { int readSize = responseStream.Read(buffer, 0, buffer.Length); if (readSize == 0) { break; } fs.Write(buffer, 0, readSize); } }