ファイルのアップロードは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);
}
}