none
FTPでホスト上のファイル属性変更 RRS feed

  • 質問

  • 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);
            }


    2006年11月17日 7:19

回答

  • TcpClientクラスを使って地道にやるしかないんじゃないでしょうか? 以下の本が参考になると思います。

    Visual C#.netではじめるネットワークプログラミング2 FTP編

    2006年11月18日 5:22
    モデレータ
  •  えすとれど さんからの引用


    ファイルのアップロード、ダウンロード、ディレクトリ作成などの機能は実装できています。

    これらの機能はWebRequestを使って実装しました。

    ファイル属性の操作も同様に実装できればよさそうなものですが、相当するWebRequestMethodsがみつかりませんでした。

    それらの操作と属性変更には、ある違いがあります。

    そもそも FTP には「属性変更コマンド」というのが存在しません。

    ファイルの属性はホストのプラットフォームによって異なり、事実上の標準としては Unix 系の「rwxrwxrwx」という形が使われますが、例えば Windows ホストだったら、おなじみの「読み取り専用/隠しファイル」というような属性を返しても間違いではありません。

    FTP はプラットフォームに依存しないプロトコルなので、プラットフォームに依存する属性変更コマンドは規定されていないのです。

    そこで、一般には(ホストは Unix 系が多いだろうということで)「SITE CHMOD」というコマンドを使います。

    SITE は、後続のコマンドラインをホストプラットフォームに直接渡します。CHMOD とは、Unix 系の OS で、ファイルの属性を変更するコマンドです(ですから、Windows 上で動くサーバだったら、SITE ATTRIB になるかもしれません)。

    で、肝心なポイントですが、FtpWebRequest は SITE コマンドをサポートしません。試しに Method プロパティに SITE コマンドを設定したら ArgumentException を吐いてしまいました。

    結論としてはすでに出ていますが、FtpWebRequest は使えません。

    2006年11月18日 8:18

すべての返信

  • TcpClientクラスを使って地道にやるしかないんじゃないでしょうか? 以下の本が参考になると思います。

    Visual C#.netではじめるネットワークプログラミング2 FTP編

    2006年11月18日 5:22
    モデレータ
  •  えすとれど さんからの引用


    ファイルのアップロード、ダウンロード、ディレクトリ作成などの機能は実装できています。

    これらの機能はWebRequestを使って実装しました。

    ファイル属性の操作も同様に実装できればよさそうなものですが、相当するWebRequestMethodsがみつかりませんでした。

    それらの操作と属性変更には、ある違いがあります。

    そもそも FTP には「属性変更コマンド」というのが存在しません。

    ファイルの属性はホストのプラットフォームによって異なり、事実上の標準としては Unix 系の「rwxrwxrwx」という形が使われますが、例えば Windows ホストだったら、おなじみの「読み取り専用/隠しファイル」というような属性を返しても間違いではありません。

    FTP はプラットフォームに依存しないプロトコルなので、プラットフォームに依存する属性変更コマンドは規定されていないのです。

    そこで、一般には(ホストは Unix 系が多いだろうということで)「SITE CHMOD」というコマンドを使います。

    SITE は、後続のコマンドラインをホストプラットフォームに直接渡します。CHMOD とは、Unix 系の OS で、ファイルの属性を変更するコマンドです(ですから、Windows 上で動くサーバだったら、SITE ATTRIB になるかもしれません)。

    で、肝心なポイントですが、FtpWebRequest は SITE コマンドをサポートしません。試しに Method プロパティに SITE コマンドを設定したら ArgumentException を吐いてしまいました。

    結論としてはすでに出ていますが、FtpWebRequest は使えません。

    2006年11月18日 8:18
  • TcpClientですね。
    試してみます。
    ありがとうございました。

    Visual C#.netではじめるネットワークプログラミング2 FTP編は、以前ちらちらっと立ち読みしたことがあります。

    今回の目的はファイルの属性さえ変更できればよいのですが、この書籍はむしろ、通信の仕組みを根本から知りたい人向けにかかれているような印象をうけたので、見送ってました。

    再度、チェックしてみます。
    2006年11月19日 15:58
  • 非常に丁寧なレス、ありがとうございます。

    参考になります。

    >そもそも FTP には「属性変更コマンド」というのが存在しません。

    なるほど。

    いくら探しても見つからないわけですね。

    >そこで、一般には(ホストは Unix 系が多いだろうということで)「SITE CHMOD」というコマンドを使います。

    FFFTPのログを見たところ、目的のサーバではSITE CHMODで属性が変わっていました。

    このコマンドを使えばよさそうですね。


    >FtpWebRequest は SITE コマンドをサポートしません。試しに Method プロパティに SITE コマンドを設定したら ArgumentException を吐いてしまいました。

    私も試してみました。

    同様に例外がでました。

    SITEがFTPのコマンドではないのだから、妥当な振る舞いですね。

    TcpClientを使って実装を試みてみます。

    2006年11月19日 16:03
  •  えすとれど さんからの引用
    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が終点を表すのが一般的なのか、このサーバーに固有な使用なのかはわかりません。

    これから調べてみます。
    2006年11月19日 17:32