ファイルのアップロードはC#では簡単である。 ID、パスワードでアクセス管理されているFTPサイトへアップロードするには、次のようにすればよい。
WebClient wc = new WebClient(); wc.Credentials = new NetworkCredential("id", "password"); wc.UploadFile(uri, localpath);
NetworkCredentialコンストラクタの引数にはアクセス権のあるIDとパスワードを文字列型で与える。
ディレクトリの作成の方が少し面倒である。 アップロードと同じWebClientクラスのインスタンスで実行できた方がありがたいのであるが、 マニュアルをざっとみた限りでは、該当機能が見つからなかった。
WebRequestクラスを使って、次のようにする。
ディレクトリの削除はMethodプロパティに WebRequestMethods.Ftp.RemoveDirectory
を指定する。
ファイルの削除はMethodプロパティに WebRequestMethods.Ftp.DeleteFile
を指定する。
WebRequest request = WebRequest.Create(uri); request.Method = WebRequestMethods.Ftp.MakeDirectory; request.Credentials = new NetworkCredential("id", "password"); using (var resp = (FtpWebResponse)request.GetResponse()) { Console.WriteLine(resp.StatusCode); }
FTPサイトのディレクトリやファイルの照合は行わず、 前回アップロードを実行した時刻以降に作成、更新したファイルのみアップロードしている。 新たなディレクトリがあれば、FTPサイトに作成している。
したがって、ディレクトリやファイルの削除には対応していない。 これは、削除が少ないことと、削除に対応するとプログラムの実行時間が長くなることによる。
新規ディレクトリが見つかると、ファイルのアップロードとは別に ディレクトリ毎にWebRequestインスタンスを生成して、FTPサイトにディレクトリを作成している。 多くの新規ディレクトリが存在する場合、効率が悪いことになるが、実際の運用では、 ファイルの新規作成や更新が殆どであり、ディレクトリの作成はごくまれなため、問題にならない。
// upload.cs 2020.3.21/2013.3.9 // 前回アップロードした時刻以降で更新または作成された // ファイルをサーバーにアップロードする。 // csc /out:c:\gis\bin\upload.exe c:\gis\src\upload.cs using System; using System.IO; using System.Net; class Upload { const string DIR = @"c:\www"; const string TimeStampFile = "c:/gisstat/timestamp.dat"; string srv, id, pw; DateTime dtLast; WebClient wc; public Upload() { Console.Write("password:"); pw = Console.ReadLine(); // パスワード入力 if (File.Exists(TimeStampFile)) { dtLast = File.GetLastWriteTime(TimeStampFile); // 前回のアップロード時間 File.SetLastWriteTime(TimeStampFile, DateTime.Now); // タイムスタンプ更新 } else { dtLast = new DateTime(1,1,1); File.WriteAllText(TimeStampFile, ""); } try { srv = "ftp://サーバー名"; id = "ID"; wc = new WebClient(); wc.Credentials = new NetworkCredential(id, pw); scan(DIR); wc.Dispose(); } catch (Exception e) { Console.WriteLine(e); } } void scan(string dir) { foreach (string path in Directory.GetFiles(dir)) { string uri = srv + path.Substring(DIR.Length).Replace(@"\", "/"); DateTime dtCR = Directory.GetCreationTime(path); DateTime dtLW = Directory.GetLastWriteTime(path); if (dtCR > dtLast || dtLW > dtLast) { // 更新または新規ファイル try { byte[] response = wc.UploadFile(uri, path); Console.WriteLine("upload: " + path + " " + System.Text.Encoding.ASCII.GetString(response)); } catch (Exception e) { System.Windows.Forms.MessageBox.Show(e.ToString()); } } } foreach (string path in Directory.GetDirectories(dir)) { if (path == "c:\\www\\www08") continue; string uri = srv + path.Substring(DIR.Length).Replace(@"\", "/"); DateTime dt = Directory.GetCreationTime(path); if (dt > dtLast) { Console.WriteLine("新規ディレクトリ: " + uri); try { WebRequest request = WebRequest.Create(uri); request.Method = WebRequestMethods.Ftp.MakeDirectory; request.Credentials = new NetworkCredential(id, pw); using (var resp = (FtpWebResponse)request.GetResponse()) { Console.WriteLine(resp.StatusCode); } } catch (Exception ex) { Console.WriteLine(ex); } } scan(path); } } static void Main() { new Upload(); System.Threading.Thread.Sleep(1000); } }