Grow up

生活とプログラミング

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/

f:id:knkomko:20210505003922p:plain:w450

サインオンの画面ではアカウント情報を入力します。
[Log On]ボタンを押下するとFTPサーバに接続できます。

ユーザー名:xuser
パスワード:xpass

f:id:knkomko:20210505154820p:plain:w450

C#でファイル転送

FTPサーバーにファイル転送を行うサンプルになります。
f:id:knkomko:20210505162802p:plain:w450

サンプルの作成にあたって参考にした公式ドキュメントです。
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);
    }
}