wininetを使用してFTPにてファイルをダウンロードするには?

解決


Hevia  2005-07-06 09:04:06  No: 90849  IP: [192.*.*.*]

はじめまして、いつも参考にさせていただいています。
現在、wininetのFtpGetFileを使用してサーバよりファイルをダウンロードしようとしているのですが、
FtpPutFileはうまくいくのですが、FtpGetFileの方はうまくいきません。
Putはできているので、原因はFtpGetFileにあるのでしょうが、
問題点がよくわかりません。
どこを直せばいいのか、ご教授願います。
環境はWinXPのVB.NETです。
よろしくお願いします。


***** 以下コード *****

Public Declare Function FtpGetFile Lib "wininet.dll" Alias "FtpGetFileA" ( _
            ByVal hFtpSession As Integer, _
            ByVal lpszRemoteFile As String, _
            ByRef lpszNewFile As String, _
            ByVal fFailIfExists As Boolean, _
            ByVal dwFlagsAndAttributes As Integer, _
            ByVal dwFlags As Integer, _
            ByVal dwContext As Integer) As Boolean
            

======= 以下メイン処理 ===========
            
Dim hOpen As Integer
Dim hFtpSession As Integer
Const INTERNET_FLAG_RELOAD As Integer = &H80000000
Const INTERNET_FLAG_TRANSFER_BINARY As Short = &H2S
Const INTERNET_NO_CALLBACK As Short = 0
        
hOpen = InternetOpen("vb wininet", INTERNET_OPEN_TYPE_DIRECT, vbNullString, vbNullString, 0)
hFtpSession = InternetConnect(hOpen, "FtpServer", INTERNET_INVALID_PORT_NUMBER, _
      "FtpUser", "FtpPass", INTERNET_SERVICE_FTP, nFlag, 0)

FtpGetFile(hFtpSession, "/xxx/xxxx/yyyy.ini", "c:\yyyy.ini", True, 0, _
    INTERNET_FLAG_TRANSFER_BINARY Or INTERNET_FLAG_RELOAD, INTERNET_NO_CALLBACK)

編集 削除
ねろ  2005-07-06 09:55:41  No: 90850  IP: [192.*.*.*]

取りあえず  err.LastDllErrorとInternetGetLastResponseInfoで
エラーの原因を分析することが先決です。

編集 削除
Hevia  2005-07-06 11:31:03  No: 90851  IP: [192.*.*.*]

ねろ様、ご回答ありがとうございます。
InternetGetLastResponseInfoなのですが、使い方が悪いのか情報取得できませんでした。
下記のような感じで使用しているのですが、何処に問題があるのでしょうか?

Dim strBuffer As String
Dim intLength As Integer

InternetGetLastResponseInfo(Err.LastDllError, vbNullString, intLength)
strBuffer = New String(Chr(0), intLength + 1)
InternetGetLastResponseInfo(Err.LastDllEroor, strBuffer, intLength)
MsgBox(strBuffer)

InternetGetLastResponseInfoを使用する前のErr.LastDllErrorは"123"で、
strBufferの値は""でした。

編集 削除
ねろ  2005-07-06 11:57:25  No: 90852  IP: [192.*.*.*]

先ず
>Err.LastDllErrorは"123"
エラーの番号だけでは何のエラーが発生したかわかりませんよね。
FormatMessageでエラーメッセージを取得します。
ちなみにFormatMessage取得した結果123は
「ファイル名、ディレクトリ名、またはボリューム ラベルの構文が間違っています。」
です。
心当たりは?

>InternetGetLastResponseInfoなのですが、使い方が悪いのか情報取得できませんでした。
WinInetのエラーは  12000以上です、すなわちWinInetのエラーでは無いからでは。

編集 削除
Hevia  2005-07-06 13:43:13  No: 90853  IP: [192.*.*.*]

InternetGetLastResponseInfoは、そういうことだったのですね。
FormatMessage、こちらでも確認致しました。
ファイル名、ディレクトリ名、またはボリューム ラベルの構文が間違っているということは、
プログラム上の問題ではなく、
FtpGetFileに渡している第2,第3引数の値が間違っているって事ですかね?
これは何度も確認して間違ってはいないようなのですが・・・
(元々はVB6で作成されたものをVB.NETにアップグレードしたものなので、
引数の値に問題は無いと思います)

編集 削除
ねろ  2005-07-06 14:46:15  No: 90854  IP: [192.*.*.*]

FtpFindFirstFileで「"/xxx/xxxx/yyyy.ini"」が見つかるかどうか調べてみたらいかがですか?

>FtpGetFile(hFtpSession, "/xxx/xxxx/yyyy.ini", "c:\yyyy.ini",False, 0, _
        INTERNET_FLAG_TRANSFER_BINARY Or INTERNET_FLAG_RELOAD, INTERNET_NO_CALLBACK)

iniファイルってbinaryだっけ、それと「INTERNET_FLAG_RELOAD」FTPでキャッシュから読み込まれる
ことはあったっけ。
5番目の引数の  ByVal dwFlagsAndAttributes As Integer  の0って何だっけ。

良くわからないけど、取りあえず一回これでやってみよう。
FtpGetFile(hFtpSession, "/xxx/xxxx/yyyy.ini", "c:\yyyy.ini",False, 32, 1, 0)

編集 削除
Hevia  2005-07-06 16:12:26  No: 90855  IP: [192.*.*.*]

FtpFindFirstFileで確認して、こちらの方は大丈夫でした。

iniファイルはASCIIですね。というよりも間違いだらけ?(汗
VB6のソースも見直したほうが良さそうですね・・・

FtpGetFile(hFtpSession, "/xxx/xxxx/yyyy.ini", "c:\yyyy.ini",False, 32, 1, 0)
でやってみても、やはり駄目でした。
同じエラーメッセージが出ます。

編集 削除
ねろ  2005-07-06 16:44:04  No: 90856  IP: [192.*.*.*]

FtpSetCurrentDirectoryでGetするパスに移動して、ファイル指定だけで
Getしてみて下さい。
クライアントの方もフォルダーに移動して、ファイル名だけ指定で。

編集 削除
でヴぃけい  2005-07-06 16:45:09  No: 90857  IP: [192.*.*.*]

サーバがLinax日本語版だとwininet.dllの関数達は
誤動作してました。
英語版だと平気なんですけど。
回避策はftpコマンドをプログラムで組み立てて
バッチファイルに書込んで起動すれば・・・・
かなり原始的ですが・・・

余計な情報だったらすいません。

編集 削除
Hevia  2005-07-07 09:29:12  No: 90858  IP: [192.*.*.*]

>ねろ様
やはり駄目でした。
とりあえず、わからないAPIよりもjavaでFTP通信するプログラムを
以前作った物があるので、それを流用するか、
Socketを使った方法で作成したらうまくいったので、どちらかでやろうかと思います。

>でヴぃけい様
回答ありがとうございます。
サーバはAIXで、今までVB6で作成したwininet.dllの関数が動いてますので、
それに関しては問題ないと思います。

答えてくださった方々、ありがとうございました。

編集 削除
おなまえ  2005-07-27 11:35:11  No: 90859  IP: [192.*.*.*]

引数の宣言が間違っています。

Public Declare Function FtpGetFile Lib "wininet.dll" Alias "FtpGetFileA" ( _
            ByVal hFtpSession As Integer, _
            ByVal lpszRemoteFile As String, _
   ByVal ⇒ ByRef lpszNewFile As String, _
            ByVal fFailIfExists As Boolean, _
            ByVal dwFlagsAndAttributes As Integer, _
            ByVal dwFlags As Integer, _
            ByVal dwContext As Integer) As Boolean

ってか、もう遅いかな〜

編集 削除
ねろ  2005-07-27 11:59:58  No: 90860  IP: [192.*.*.*]

おお!  違ってる、しかもエラーコードどうり。
宣言はチェックしなかったような気がする。(^^;

編集 削除
魔界の仮面弁士  2005-07-27 12:02:30  No: 90861  IP: [192.*.*.*]

> おなまえさん
その宣言も間違っているような。 As Boolean → As Long ですね。
http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi?print+200410/04100037.txt

編集 削除
ねろ  2005-07-27 14:03:33  No: 90862  IP: [192.*.*.*]

VB.NETですから
>As Boolean → As Long
では無く、
As Boolean → As Integer
又は
As Boolean → As Int32
ですか。

編集 削除
魔界の仮面弁士  2005-07-27 16:30:03  No: 90863  IP: [192.*.*.*]

おぉっと。今回は VB.NETでしたっけか。失礼。
フォローありがとうございます。>ねろさん

もし、Boolean型で実装したいなら、VB.NET では
  『<MarshalAs(UnmanagedType.Bool)> ByVal failIfExists As Boolean』
のように書いてあげれば OK ですかね。(戻り値も同様)


# そういえば、.NET の Boolean型って何バイトなんだろう。
http://www.microsoft.com/japan/msdn/library/ja/vblr7/html/vagrpdatatype.asp
# を見ると、2バイトっぽいけれど、Marshal.SizeOf() で調べると 4 が返された……。

編集 削除