トップ回答者
FTPでホスト上のファイル属性変更

質問
-
FTPクライアント機能をもつアプリケーションを作っています。
ホスト上のファイルの属性を取得・変更するにはどうすればよいでしょうか?
ファイルのアップロード、ダウンロード、ディレクトリ作成などの機能は実装できています。
これらの機能はWebRequestを使って実装しました。
ファイル属性の操作も同様に実装できればよさそうなものですが、相当するWebRequestMethodsがみつかりませんでした。
参考までに、ファイルアップロードの部分をアップしておきます。
WebRequest req = WebRequest.Create(uri);
req.Credentials = GetCredential();
req.Method = WebRequestMethods.Ftp.UploadFile;
using (Stream st = req.GetRequestStream())
using (FileStream fs = new FileStream(file, FileMode.Open))
{
Byte[] buf = new Byte[1024];
int count = 0;
do
{
count = fs.Read(buf, 0, buf.Length);
st.Write(buf, 0, count);
} while (count != 0);
}
回答
-
えすとれど さんからの引用
ファイルのアップロード、ダウンロード、ディレクトリ作成などの機能は実装できています。
これらの機能はWebRequestを使って実装しました。
ファイル属性の操作も同様に実装できればよさそうなものですが、相当するWebRequestMethodsがみつかりませんでした。それらの操作と属性変更には、ある違いがあります。
そもそも FTP には「属性変更コマンド」というのが存在しません。
ファイルの属性はホストのプラットフォームによって異なり、事実上の標準としては Unix 系の「rwxrwxrwx」という形が使われますが、例えば Windows ホストだったら、おなじみの「読み取り専用/隠しファイル」というような属性を返しても間違いではありません。
FTP はプラットフォームに依存しないプロトコルなので、プラットフォームに依存する属性変更コマンドは規定されていないのです。
そこで、一般には(ホストは Unix 系が多いだろうということで)「SITE CHMOD」というコマンドを使います。
SITE は、後続のコマンドラインをホストプラットフォームに直接渡します。CHMOD とは、Unix 系の OS で、ファイルの属性を変更するコマンドです(ですから、Windows 上で動くサーバだったら、SITE ATTRIB になるかもしれません)。
で、肝心なポイントですが、FtpWebRequest は SITE コマンドをサポートしません。試しに Method プロパティに SITE コマンドを設定したら ArgumentException を吐いてしまいました。
結論としてはすでに出ていますが、FtpWebRequest は使えません。
すべての返信
-
えすとれど さんからの引用
ファイルのアップロード、ダウンロード、ディレクトリ作成などの機能は実装できています。
これらの機能はWebRequestを使って実装しました。
ファイル属性の操作も同様に実装できればよさそうなものですが、相当するWebRequestMethodsがみつかりませんでした。それらの操作と属性変更には、ある違いがあります。
そもそも FTP には「属性変更コマンド」というのが存在しません。
ファイルの属性はホストのプラットフォームによって異なり、事実上の標準としては Unix 系の「rwxrwxrwx」という形が使われますが、例えば Windows ホストだったら、おなじみの「読み取り専用/隠しファイル」というような属性を返しても間違いではありません。
FTP はプラットフォームに依存しないプロトコルなので、プラットフォームに依存する属性変更コマンドは規定されていないのです。
そこで、一般には(ホストは Unix 系が多いだろうということで)「SITE CHMOD」というコマンドを使います。
SITE は、後続のコマンドラインをホストプラットフォームに直接渡します。CHMOD とは、Unix 系の OS で、ファイルの属性を変更するコマンドです(ですから、Windows 上で動くサーバだったら、SITE ATTRIB になるかもしれません)。
で、肝心なポイントですが、FtpWebRequest は SITE コマンドをサポートしません。試しに Method プロパティに SITE コマンドを設定したら ArgumentException を吐いてしまいました。
結論としてはすでに出ていますが、FtpWebRequest は使えません。
-
非常に丁寧なレス、ありがとうございます。
参考になります。>そもそも FTP には「属性変更コマンド」というのが存在しません。
なるほど。
いくら探しても見つからないわけですね。>そこで、一般には(ホストは Unix 系が多いだろうということで)「SITE CHMOD」というコマンドを使います。
FFFTPのログを見たところ、目的のサーバではSITE CHMODで属性が変わっていました。
このコマンドを使えばよさそうですね。
>FtpWebRequest は SITE コマンドをサポートしません。試しに Method プロパティに SITE コマンドを設定したら ArgumentException を吐いてしまいました。
私も試してみました。
同様に例外がでました。
SITEがFTPのコマンドではないのだから、妥当な振る舞いですね。
TcpClientを使って実装を試みてみます。
-
えすとれど さんからの引用 FTPクライアント機能をもつアプリケーションを作っています。
ホスト上のファイルの属性を取得・変更するにはどうすればよいでしょうか?
ファイルのアップロード、ダウンロード、ディレクトリ作成などの機能は実装できています。
これらの機能はWebRequestを使って実装しました。
ファイル属性の操作も同様に実装できればよさそうなものですが、相当するWebRequestMethodsがみつかりませんでした。
参考までに、ファイルアップロードの部分をアップしておきます。
WebRequest req = WebRequest.Create(uri);
req.Credentials = GetCredential();
req.Method = WebRequestMethods.Ftp.UploadFile;
using (Stream st = req.GetRequestStream())
using (FileStream fs = new FileStream(file, FileMode.Open))
{
Byte[] buf = new Byte[1024];
int count = 0;
do
{
count = fs.Read(buf, 0, buf.Length);
st.Write(buf, 0, count);
} while (count != 0);
}
このようなコードでファイル属性変更できました。
public void SetFileAttribute()
{
try
{
System.Net.Sockets.TcpClient tcp = new System.Net.Sockets.TcpClient(host, 21);
System.Net.Sockets.NetworkStream stream = tcp.GetStream();
StreamToDebugOutput(new StreamReader(stream));
StreamWriter writer = new StreamWriter(stream);
writer.AutoFlush = true;
writer.WriteLine("USER " + user);
StreamToDebugOutput(new StreamReader(stream));
writer.WriteLine("PASS " + password);
StreamToDebugOutput(new StreamReader(stream));
writer.WriteLine("SITE CHMOD " + attribute.ToString() + " " + file);
StreamToDebugOutput(new StreamReader(stream));
}
catch
{
}
}
void StreamToDebugOutput(StreamReader rdr)
{
int i = rdr.Peek();
while (i != -1)
{
String line = rdr.ReadLine();
System.Diagnostics.Debug.WriteLine(line);
i = rdr.Peek();
}
}
Writerで情報を送信するごとに、StreamReaderをnewしないとサーバーからの応答が正しく得られませんでした。
newした後に送信した情報の応答がえられないようです。
また、読込の終点がEndOfStreamでは取得できませんでした。
これを目印にしてReadを続けたら固まりました。
ReadToEndでも同様でした。
ストリームを見ていると、-1が終点を表しているようだったのでPeekで-1を監視するという方法で解決しました。
しかし、-1が終点を表すのが一般的なのか、このサーバーに固有な使用なのかはわかりません。
これから調べてみます。