tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルFTPのGetFileSizeでエラーがでる
記事No10082
投稿日: 2010/04/27(Tue) 13:31
投稿者AMI
現在VB2005で、FTPソフトを作成しています。
アップロードされている、ファイルサイズを取得するという
単純なものです。

状況が、Aプロバイダ・Bプロバイダとあり、
同じソースで、Aでは正常に取得できますが、
Bでしますと、エラーになり、
エラー番号が「5」
メッセージが
「リモート サーバーがエラーを返しました: (550) ファイルが使用できません (例: ファイルが見つからない、ファイルへのアクセスがない)」
というエラーメッセージが表示されます。
プロバイダにより使えるコマンドがちがうのでしょうか?
ちなみにA・Bともに同じ構成、ファイルアクセス権限で設定しております。

それとファイルサイズを取得する設定
        'ftpReq.Method = System.Net.WebRequestMethods.Ftp.GetFileSize

        ftpReq.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails
に変更すると、そればともにエラーがでずにファイル構成を取得できます。


        Dim u As New Uri("ftp://xxx.ne.jp/www/12.log")

        'FtpWebRequestの作成
        Dim ftpReq As System.Net.FtpWebRequest = _
            CType(System.Net.WebRequest.Create(u), System.Net.FtpWebRequest)
        'ログインユーザー名とパスワードを設定
        ftpReq.Credentials = New System.Net.NetworkCredential("XXXX", "○○○")
        'MethodにWebRequestMethods.Ftp.ListDirectoryDetails("LIST")を設定
        ftpReq.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails
        'ftpReq.Method = System.Net.WebRequestMethods.Ftp.GetFileSize
        '要求の完了後に接続を閉じる
        ftpReq.KeepAlive = False
        'PASSIVEモードを無効にする
        ftpReq.UsePassive = False

        'FtpWebResponseを取得
        Dim ftpRes As System.Net.FtpWebResponse = _
            CType(ftpReq.GetResponse(), System.Net.FtpWebResponse)
        'FTPサーバーから送信されたデータを取得
        Dim sr As New System.IO.StreamReader(ftpRes.GetResponseStream())
        Dim res As String = sr.ReadToEnd()
        Dim lngFileSize As Long = ftpRes.ContentLength
        'ファイル一覧を表示
        Console.WriteLine(res)
        Label1.Text = res

[ツリー表示へ]
タイトルRe: FTPのGetFileSizeでエラーがでる
記事No10083
投稿日: 2010/04/28(Wed) 09:35
投稿者魔界の仮面弁士
> 状況が、Aプロバイダ・Bプロバイダとあり、
同じサーバーに対して、異なるインターネットプロバイダ経由で接続した場合でしょうか。
それとも、別のホスティング業者に対して FTP 接続しているという話でしょうか?

> ちなみにA・Bともに同じ構成、ファイルアクセス権限で設定しております。
FTP サーバーも同一ですか?(OS ではなく、FTP サービスソフトウェアの差異)
可能であれば、通信時のサーバーログを比較してみては如何でしょう。

もし、サーバーログを入手できないようであれば、通信ログを取得可能な
FTP クライアントソフトを使って、それぞれのコマンドの動作を調べてみて下さい。

あるいは、"Microsoft Network Monitor" を用いて、それぞれの FTP 通信の内容の
違いを追いかけてみるという手もあるかと思います。

[ツリー表示へ]
タイトルRe^2: FTPのGetFileSizeでエラーがでる
記事No10084
投稿日: 2010/04/28(Wed) 13:12
投稿者AMI
早速のご回答ありがとうございます。
説明不足ですみません。
A・Bともに別プロバイダであり、それぞれの別サーバーになります。
今回、A(現状使用プロバイダ)を解約して、
Bにする予定なのですが、システムの試験をしているときに
そのような状況になりました。
ちなみに、プロバイダ名は書き込んでいいものなのでしょうか?

[ツリー表示へ]
タイトルRe^3: FTPのGetFileSizeでエラーがでる
記事No10085
投稿日: 2010/04/28(Wed) 14:08
投稿者魔界の仮面弁士
> ちなみに、プロバイダ名は書き込んでいいものなのでしょうか?
構いませんが、書いたところで、同じプロバイダを使っている人しか
具体的な回答はできないと思います。

なのでそれよりも、先述の調査を行うことの方が先決かと思いますよ。


> システムの試験をしているときに
> そのような状況になりました。
可能性として思いつくところでは――

・以前は大文字小文字を区別しないサーバーだったが、今回は区別されている。
・それぞれのサーバーで、ログオン直後のカレントディレクトリが異なっている。
・サーバーBでは、SIZE コマンドに対するパーミッションが異なっている。

[ツリー表示へ]
タイトルRe^4: FTPのGetFileSizeでエラーがでる
記事No10087
投稿日: 2010/04/28(Wed) 16:51
投稿者AMI
ご回答ありがとうございます。
ちなみに同じファイルに対して、
下記のようにファイル情報を取得するコマンドを発行しますと
       ftpReq.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails

正常に、受信することから、
1.以前は大文字小文字を区別しないサーバーだったが、今回は区別されている。
2.それぞれのサーバーで、ログオン直後のカレントディレクトリが異なっている
1と2については、問題ないように思います。

下記については、どのように設定するのですか?
ファイル自体のパーミッションは、Aサーバーと同様に
「666」で設定しております。
コマンドごとにパーミッションを設定できるのでしょうか?

・サーバーBでは、SIZE コマンドに対するパーミッションが異なっている

[ツリー表示へ]
タイトルRe^5: FTPのGetFileSizeでエラーがでる
記事No10088
投稿日: 2010/04/28(Wed) 17:46
投稿者魔界の仮面弁士
> 下記については、どのように設定するのですか?
それはサーバー管理者に問い合わせてください。
(そもそも、そうした追加の権限設定が存在しないサーバーも少なくありません)


ただし先ほどからの繰り返しになりますが、まずは『原因の調査』が先だと思いますよ。

そもそも原因すら分かっていない段階で、想定される対処法を虱潰しに試してみたところで、
無駄な作業になってしまう可能性が高いと思います。第一、複数の要因による複合的な問題で
あったとしたら、運よく解決したとしても、何が問題であったのか分からなくなってしまいます。



今回の場合、GetFileSize (FTP の SIZE コマンド) に対して失敗しているのですから、
 (1) そのサーバーが、SIZE コマンドをサポートしているかどうかを確認する。
 (2) SIZE が使えるなら、VB.NET からの通信結果が正しいかどうかを確認する。
という調査を先に行ってみては如何でしょう。


(1) については、手動で FTP コマンドを送信できるツールで試してみてください。

その結果、SIZE が使えなかったなら、.NET からの GetFileSize も使えないことになるでしょう。
LIST は RFC959 で定義された標準的なコマンドなので、大抵のサーバーで利用できますが、
SIZE は RFC3659 で追加定義されたコマンドであり、サポートしていないサーバーも存在します。


たとえば、フリーソフトの FFFTP であれば、目標の www ディレクトリに移動した後で、
[コマンド]-[任意のコマンド]で『SIZE 12.log』などとすれば、正常動作時には
200 番台の正常系コード(213 など)と共に、ファイルサイズが得られるはずです。
一方、未実装であれば 500番台のコード(おそらく 502)が返されるかと思います。

あるいは Windows 標準の FTP.EXE でも構いません。目標のディレクトリに移動した後で、
『literal SIZE 12.log』のコマンドを試してみて下さい。


それらを試してみた結果、そもそもファイルサイズが返されないのであれば、
サーバー側の制限という可能性もありますので、SIZE コマンドが使用可能かどうか、
サーバー管理者に問い合わせてみた方が良いかと思います。
(なお SIZE の結果は、STRU/MODE/TYPE の指定により異なる可能性があります)


その反対に、手動操作でサイズを取得できるようであれば、今度は別ディレクトリから
SIZE /www/12.log などといったルートからのパス指定が使えるかも調査しておいた方が
良いかもしれません。



次に (2) の方ですが…これはサーバーAおよびサーバーBにおける通信ログを
比較するのが一番です。もし、サーバーログを取得できないようであれば、
前々回に紹介したモニタリングソフトなどを用いて、両サーバーに対する通信内容を
FtpWebRequest での通信時と FTP ツールでの通信時とのそれぞれで比較してみてください。

[ツリー表示へ]
タイトルRe^6: FTPのGetFileSizeでエラーがでる
記事No10093
投稿日: 2010/05/07(Fri) 15:58
投稿者AMI
詳しい内容の回答ありがとうございます。
指示どおりに、確認したところ、
FFFTPより手動でコマンドを投げたところ、
古いサーバーでは、下記のように結果が返ってきて、
******************
SIZE c.log
213 43
******************
新しいサーバーでは、下記のように返ってきました。
******************
SIZE c.log
550 SIZE not allowed in ASCII mode
******************
やはり、新しいサーバーでは、
LIST コマンドはサポートしているが、
SIZE コマンドはサポートしていないということなのでしょうか?

[ツリー表示へ]
タイトルRe^7: FTPのGetFileSizeでエラーがでる
記事No10094
投稿日: 2010/05/07(Fri) 16:32
投稿者魔界の仮面弁士
> SIZE コマンドはサポートしていないということなのでしょうか?
まだ分かりませんよ。私は前回、
 「SIZE の結果は、STRU/MODE/TYPE の指定により異なる可能性がある」
と書いていましたよね。その点の確認も行っておきましょう。


> ******************
> SIZE c.log
> 550 SIZE not allowed in ASCII mode
> ******************
550 に続くメッセージを見ると、
  SIZE コマンドは「ASCII モードでは許可されていない」
…と返されていますね。

# 未知のコマンドなら 500 が返されるでしょうし、
# 実装されていないなら、502 や 504 が返されるはず。


追加で、FFFTP から下記の FTP コマンドも試してみてください。

"STAT" … 現在の状態(TYPE等)を表示
"FEAT" … サーバに実装されている拡張コマンド(SIZE等)のリストを取得


STAT で ASCII と返されるようなら、現在のモードは、ASCII モードだと思いますので、
事前にバイナリモードにしておいてから SIZE を試してみたらどうなりますか?

FTP コマンドの場合、"TYPE A" で ASCII モード、"TYPE I" でバイナリモードになります。
一方、FtpWebRequest クラスの場合は UseBinary プロパティで切り替わります。

[ツリー表示へ]
タイトルRe^8: FTPのGetFileSizeでエラーがでる
記事No10095
投稿日: 2010/05/07(Fri) 17:13
投稿者AMI
早速のお返事ありがとうございます。
FFFTPで試したところ

> "STAT" … 現在の状態(TYPE等)を表示
現在はASCIIモードでした。
> "FEAT" … サーバに実装されている拡張コマンド(SIZE等)のリストを取得
SIZEコマンドも表示されたので、実装されているとおもいます。

そこで、
FTP コマンドの場合、"TYPE I" でバイナリモードに変更したあと、
SIZEコマンドを実行したら、正常に取得できました。

そのことから、
サーバー自体はSIZEコマンドをサポートしているということはわかりました。

あとはそれをVBで実装させるだけなのですが、
調べたところ、標準で「UseBinary」モードはTRUEになっていました。
しかし、もう一度下記のように、Trueに設定してあげても、
同様のエラーが表示されます。
            ftpReq.Method = System.Net.WebRequestMethods.Ftp.GetFileSize
            ftpReq.UseBinary = True

他に設定するプロパティがあるのでしょうか?

[ツリー表示へ]
タイトルRe^9: FTPのGetFileSizeでエラーがでる
記事No10096
投稿日: 2010/05/07(Fri) 20:18
投稿者魔界の仮面弁士
> サーバー自体はSIZEコマンドをサポートしているということはわかりました。
一歩前進ですね。


> あとはそれをVBで実装させるだけなのですが、
次は、そもそも FtpWebRequest がそれに対応しているのかどうか…ですね。

まずは、No10083 で示した "Microsoft Network Monitor" を使って、
FtpWebRequest が送出している内容を追ってみては如何でしょう。


で、手元の環境(IIS)で見たところ、GetFileSize を投げると
 ★GetFileSize 開始★
 "USER アカウント名"
 "PASS パスワード"
 "OPTS utf8 on" … Unicode 対応のサーバーなら Unicode を使う
 "PWD" … 現在のディレクトリを調べている
 "CWD 階層"  … 対象ファイルのディレクトリに移動
 "SIZE ファイル名"
 "QUIT" … 切断
という手順が行われているのみで、バイナリモードへの変更は行われて
いないように見えました。(そちらの環境でも試してみて下さい)


しかし当方のサーバーでは、以下のようにすると TYPE I で SIZE が送出されました。
(他のサーバーではどうなるか分かりませんが)


手順としては、GetFileSize(SIZE コマンド)を送出する前に、先んじて
DownloadFile(RETR コマンド)などの「UseBinary が利きそうなコマンド」を
同一接続で送出しておくというものです。


通信内容を Network Monitor で監視してみたところ、このようになりました。

 ★DownloadFile開始★ … UseBinary = True、KeepAlive = True
 "USER アカウント名"
 "PASS パスワード"
 "OPTS utf8 on"
 "PWD"
 "CWD 階層"
 "TYPE I" … UseBinary が利いて、バイナリモードに変換される
 "RETR ファイル名" … サイズの小さなファイルを取得しておく
 ★GetFileSize 開始★ … UseBinary = 任意、KeepAlive = False
 "SIZE ファイル名" … 前回が KeepAlive = True なので、先ほどの接続が使われる
 "QUIT" … 今回は KeepAlive = False なので、通信完了後に QUIT される


ということで、次に調査すべき点は:

(1) 上記の手順が、現在のサーバーに通用するのかを検証する。
(2) どの WebRequestMethods.Ftp であれば、"TYPE I" が送出されるのかを順に調べる。
(3) 今回の要件を、(2) のコマンドを事前に送出する運用で回避できるかを検討する。

これで回避できれば、今回の問題は解決かと思います。
一方、事前送出では都合が悪い場合には:

(4) FtpWebRequest クラス以外の別ライブラリの利用を検討する。
 http://support.microsoft.com/kb/832679
 http://www.hi-ho.ne.jp/babaq/basp21.html
 http://www.grapecity.com/japan/support/database/p7_369.htm

(5) クラスを変更することさえもできない事情がある場合には、
 FtpWebRequest が、SIZE をバイナリモードで送出できないという点について、
 Microsoft の有償サポートに問い合わせてみる。

[ツリー表示へ]
タイトルRe^10: FTPのGetFileSizeでエラーがでる
記事No10097
投稿日: 2010/05/10(Mon) 09:43
投稿者AMI
おはようございます。
通信内容を Network Monitor でモニタリングすると、
仮面弁士様と同じような動作になりました。
そこで、
「★DownloadFile開始★」処理をした後
「★GetFileSize 開始★」を行うことで、
理想どおりの処理が完成しました。

やはり、BINARY転送がGetFileSize だけでは、適応されず、
一回 DownloadFileをBINARYで行うことで、解決できました。

今回、「Network Monitor」を初めて使いましたが、
大変勉強になりました。
ありがとうございました。

[ツリー表示へ]
タイトルRe^11: FTPのGetFileSizeでエラーがでる
記事No10098
投稿日: 2010/05/10(Mon) 10:44
投稿者魔界の仮面弁士
解決できたようでなによりです。

> やはり、BINARY転送がGetFileSize だけでは、適応されず、
> 一回 DownloadFileをBINARYで行うことで、解決できました。

.NET Framework 2.0/3.5/4 それぞれで ftp.microsoft.com に接続したところ、
やはり GetFileSize では UseBinary は無視されていたようです。
(SIZE 自体は取得できましたが、TYPE I が送出された様子はありません)

GetFileSize で UseBinary が無視されるという現状は、サーバーによっては
今回の AMI さんのような問題を引き起こす事が分かったので、
この件は Microsoft に連絡しておこうと思っています。

その際には、具体的な話をした方が問題点を認識してもらいやすくなるかと思うのですが、
今回、問題の起きた FTP サーバーの名前を公開することはできますでしょうか?
# DrFTPD とか Mina とか ProFTPD とか Pure-FTPd とか NcFTPd Server とか…。

[ツリー表示へ]
タイトルRe^12: FTPのGetFileSizeでエラーがでる
記事No10099
投稿日: 2010/05/10(Mon) 10:56
投稿者AMI
お返事ありがとうございます。
FTPサーバーというのが、
プロバイダが提供している、FTPサーバーになるのですが、
プロバイダ名からどうのようなサーバーを使用しているのか
はわかるのでしょうか?
> 今回、問題の起きた FTP サーバーの名前を公開することはできますでしょうか?
> # DrFTPD とか Mina とか ProFTPD とか Pure-FTPd とか NcFTPd Server とか…。

[ツリー表示へ]
タイトルRe^12: FTPのGetFileSizeでエラーがでる
記事No10100
投稿日: 2010/05/10(Mon) 11:13
投稿者AMI
プロバイダ側に電話して確認したところ、
FTPサーバーは
「ProFTPD」
で動作しているとのことでした。

[ツリー表示へ]
タイトルRe^13: FTPのGetFileSizeでエラーがでる
記事No10101
投稿日: 2010/05/10(Mon) 11:17
投稿者魔界の仮面弁士
> プロバイダ側に電話して確認したところ、
> 「ProFTPD」

情報提供、ありがとうございます。m(_ _)m

connect.microsoft.com 経由か MVP インシデント経由で
今回の問題点について、Microsoft 側にフィードバックしておきますね。

[ツリー表示へ]
タイトルRe^14: FTPのGetFileSizeでエラーがでる
記事No10102
投稿日: 2010/05/10(Mon) 11:22
投稿者AMI
お手数かけますが、よろしくお願いします。
今回はいろいろ勉強になり、ありがとうございます。

[ツリー表示へ]
タイトルRe^15: FTPのGetFileSizeでエラーがでる
記事No10103
投稿日: 2010/05/11(Tue) 20:31
投稿者魔界の仮面弁士
有償サポートへの問い合わせは行っていませんが、とりあえず、
サンプルコード込で connect に投稿しておきました。
http://connect.microsoft.com/VisualStudioJapan/feedback/details/558310/

賛成▲ or 反対▼ の投票をお願いします。

[ツリー表示へ]