FTPのカレントディレクトリ変更について

解決


FTP  2004-12-28 21:11:48  No: 118559

はじめまして。
今、VB6.0にてWinInetを使用してFTPプログラムを初めて作成しているのですが
FTPのカレントディレクトリ変更がうまくいきません。

FTPサーバのC:\FTPtestをFTPサーバディレクトリに設定しています。
この1階層下の「C:\FTPtest\data」ディレクトリ内のデータを
GETしたいのですがうまくいきません。

事象としては「FtpSetCurrentDirectory」関数後に
Err.LastDllErrorプロパティを用いると
12003(パスなし?)が表示されてしまいます。

下記にソースを記述致しますのでFTPに詳しい方
是非教えて頂けないでしょうか。宜しくお願い致します。

************************************
Private Const msFtpSvr = "11.111.11.11"      'FTP Server IP
Private Const msFtpDir = "C:\FTPtest"        'FTP Server Dir
Private Const msFtpUid = "abcdefg"           'FTP Login UserID
Private Const msFtpPwd = "12345"             'FTP Login Password
Private Const msReciveDir = "E:\APP\data"    'FTP Recive Server Dir
Private Const msFtpFilNm = TENSODATA.txt     'FTP Target FileName
Private Const msRecFilNm = GETDATA.txt       'FTP Recive FileName

'AccessType
Private Const INTERNET_OPEN_TYPE_PRECONFIG = 0&     
Private Const INTERNET_OPEN_TYPE_DIRECT = 1&          
Private Const INTERNET_OPEN_TYPE_PROXY = 3&           

'File Attribute
Private Const FILE_ATTRIBUTE_READONLY = &H1&
Private Const FILE_ATTRIBUTE_HIDDEN = &H2&
Private Const FILE_ATTRIBUTE_SYSTEM = &H4&
Private Const FILE_ATTRIBUTE_DIRECTORY = &H10&
Private Const FILE_ATTRIBUTE_ARCHIVE = &H20&
Private Const FILE_ATTRIBUTE_NORMAL = &H80&
Private Const FILE_ATTRIBUTE_TEMPORARY = &H100&
Private Const FILE_ATTRIBUTE_COMPRESSED = &H800&
Private Const FILE_ATTRIBUTE_OFFLINE = &H1000&

'FTP TransferType
Private Const FTP_TRANSFER_TYPE_ASCII = &H1&
Private Const FTP_TRANSFER_TYPE_BINARY = &H2&

'Cache Flags
Private Const INTERNET_FLAG_RELOAD = &H80000000      
Private Const INTERNET_FLAG_DONT_CACHE = &H4000000   
Private Const INTERNET_FLAG_RESYNCHRONIZE = &H800     
Private Const INTERNET_FLAG_NEED_FILE = &H10        
Private Const INTERNET_FLAG_HYPERLINK = &H400         

'ConnectServerPort
Private Const INTERNET_INVALID_PORT_NUMBER = 0        
Private Const INTERNET_DEFAULT_FTP_PORT = 21          
Private Const INTERNET_DEFAULT_GOPHER_PORT = 70       
Private Const INTERNET_DEFAULT_HTTP_PORT = 80         
Private Const INTERNET_DEFAULT_HTTPS_PORT = 443       
Private Const INTERNET_DEFAULT_SOCKS_PORT = 1080      

'ConnectService
Private Const INTERNET_SERVICE_FTP = 1&               
Private Const INTERNET_SERVICE_GOPHER = 2&            
Private Const INTERNET_SERVICE_HTTP = 3&              '

'=====================================================================
'API(WinInet)定義
'=====================================================================

'WinInet を初期化
Private Declare Function InternetOpen Lib "wininet.dll" _
        Alias "InternetOpenA" _
        (ByVal lpszAgent As String, ByVal dwAccessType As Long, _
        ByVal lpszProxyName As String, ByVal lpszProxyBypass As String, _
        ByVal dwFlags As Long) As Long

'(FTP, HTTP, Gopher)サービスに接続する
Private Declare Function InternetConnect Lib "wininet.dll" _
        Alias "InternetConnectA" _
        (ByVal hInternetSession As Long, ByVal lpszServerName As String, _
        ByVal nServerPort As Integer, ByVal lpszUsername As String, _
        ByVal lpszPassword As String, ByVal dwService As Long, _
        ByVal dwFlags As Long, ByVal dwContext As Long) As Long

'カレントディレクトリを変更
Private Declare Function FtpSetCurrentDirectory Lib "wininet.dll" _
        Alias "FtpSetCurrentDirectoryA" _
        (ByVal hFtpSession As Long, ByRef lpszDirectory As Byte) As Long

'ファイルをローカルディスクにコピー
Private Declare Function FtpGetFile Lib "wininet.dll" _
        Alias "FtpGetFileA" _
        (ByVal hFtpSession As Long, ByRef lpszRemoteFile As Byte, _
        ByRef lpszNewFile As Byte, ByVal fFailIfExists As Long, _
        ByVal dwFlagsAndAttributes As Long, ByVal dwFlags As Long, _
        ByVal dwContext As Long) As Long

'WinInet で作成したハンドルをクローズ
Private Declare Function InternetCloseHandle Lib "wininet.dll" _
        (ByVal hInternet As Long) As Long

'=====================================================================

Public Function FtpImgGet()

    Dim lngInethnd   As Long    'InterNet Open Handle
    Dim lngFtphnd    As Long    'InterNet Connect Handle
    Dim lngRet       As Long    '戻り値
    Dim strFTPDir    As String  'FTP Serverの変更後CurrentDirectory
    Dim strLclDir    As String  'DownLoad したファイルを保存する Directory
    Dim bytFtpBuff() As Byte    'FTP Server 内の Download するファイル名
    Dim bytLclBuff() As Byte    'Download したファイルを保存するファイル名
    
    Dim objFileSys   As Object  

    On Error GoTo FTPDATAGETINI_ERR

    strFTPDir = msFtpDir & "\data"

    Set objFileSys = CreateObject("Scripting.FileSystemObject")

    'InternetOpen (Handle を取得)  インターネットへの接続します
    lngInethnd = InternetOpen(vbNullString, INTERNET_OPEN_TYPE_PRECONFIG, _
                                            vbNullString, vbNullString, 0)
                                            
    'InternetConnect (上記で取得した Handle で FTP Server に Connect)
    lngFtphnd = InternetConnect(lngInethnd, msFtpSvr, INTERNET_DEFAULT_FTP_PORT, _
                                            msFtpUid, msFtpPwd, INTERNET_SERVICE_FTP, 0, 0)

    'FTP Server の取得ファイルが存在する Directory
     bytFtpBuff = StrConv((strFTPDir & vbNullChar), vbFromUnicode)

'    'FTP Server の CurrentDirectory を変更
    lngRet = FtpSetCurrentDirectory(lngFtphnd, bytFtpBuff(0))

  MsgBox Err.LastDllError  ←  12003(パスなし?)が表示される。

    'FTP Server から取得するファイルの名前
    bytFtpBuff = StrConv((msFtpFilNm & vbNullChar), vbFromUnicode)

    'DownLoad 先をフルパスで指定
    strLclDir = msReciveDir & "\" & msRecFilNm
    bytLclBuff = StrConv((strLclDir & vbNullChar), vbFromUnicode)

    'ローカルに、すでに同一ファイル名が存在する場合は削除
    If objFileSys.FileExists(strLclDir) Then
        Kill strLclDir
    End If

    'DownLoad (ASCII-MODEの場合&キャッシュを使わずサーバからダウンロードを強制)
    lngRet = FtpGetFile(lngFtphnd, bytFtpBuff(0), bytLclBuff(0), 1, FILE_ATTRIBUTE_NORMAL, _
                                                  FTP_TRANSFER_TYPE_ASCII Or INTERNET_FLAG_RELOAD, 0)

    'オブジェクトの解放
    Set objFileSys = Nothing

    Exit Function

FTPDATAGETINI_ERR:

    'InternetConnect がされた後なのか判断
    If lngFtphnd <> 0 Then
        'Internet Handle Close 処理
        lngRet = InternetCloseHandle(lngFtphnd)
    End If

    End

End Function


ひろ  2004-12-28 21:30:47  No: 118560

ftpコマンドやFFFTPの様なツールで同じ事を試すとどうなりますか?
アクセス権設定は大丈夫ですか?
ftpサーバの設定は大丈夫ですか?


FTP  2004-12-28 21:48:09  No: 118561

レス有難うございます。

>ftpコマンドやFFFTPの様なツールで同じ事を試すとどうなりますか?
>アクセス権設定は大丈夫ですか?
>ftpサーバの設定は大丈夫ですか?

→設定、権限等は問題ないと思います。
  設定してあるディレクトリのデータの場合GET出来るので
  GETしてくるディレクトリの変更が上手くいっていないと考えております。


魔界の仮面弁士  2004-12-28 21:55:22  No: 118562

サーバの設定によっては、接続時に
    ftp://server/
ではなく、
    ftp://server/ユーザフォルダ/
に接続される場合がありますので、注意してください。

> 12003(パスなし?)が表示されてしまいます。
自身で設定しているサーバであれば、APIによる通信後に、
サーバ側のアクセスログを確認されてみては如何でしょう。


ねろ  2004-12-28 21:56:33  No: 118563

lngRet = FtpSetCurrentDirectory(lngFtphnd, bytFtpBuff(0))
を単に
lngRet = FtpSetCurrentDirectory(lngFtphnd,strFTPDir)
としたらどうなりますか。


FTP  2004-12-28 22:12:22  No: 118564

レス有難うございます。

>ftp://server/ユーザフォルダ/
>に接続される場合がありますので、注意してください。
→注意してみてみます。
>> 12003(パスなし?)が表示されてしまいます。
>自身で設定しているサーバであれば、APIによる通信後に、
>サーバ側のアクセスログを確認されてみては如何でしょう。
→アクセスログってどうやって見るんでしたっけ?(管理ツール?)
  初歩的な質問ですいません。

>lngRet = FtpSetCurrentDirectory(lngFtphnd,strFTPDir)
>としたらどうなりますか。
→このようにしてみましたが同じ結果でした。


魔界の仮面弁士  2004-12-28 23:51:55  No: 118565

> →アクセスログってどうやって見るんでしたっけ?(管理ツール?)
IISなら、「管理ツール」からftpサイトのプロパティを開き、
ログのプロパティにて指定されたパスに、テキスト形式の
*.log があります。

あとは、エラーになってしまうと言う APIによるFTP の場合と、
期待動作している方(ツール等によるFTP)の場合とで、
サーバ側のアクセスログを比較すれば、解決の糸口になるかと。

で、既に指摘がありますが、
> Private Declare Function FtpSetCurrentDirectory Lib "wininet.dll" _
>      Alias "FtpSetCurrentDirectoryA" _
>      (ByVal hFtpSession As Long, ByRef lpszDirectory As Byte) As Long
この宣言は、〜A系関数の呼び出しなので、文字列は
ByVal lpszDirectory As String の方が簡単でしょう。
(ByVal As String にした場合は、StrConvを行う必要が無くなります)

これがもし、W系関数である場合は、宣言を ByRef As Byte にして、
バイト配列の先頭要素を参照渡しする手法が使えますが、
この場合も、StrConv を使う必要は無いと思います。


FTP  2004-12-29 01:03:53  No: 118566

アクセスログの件有難う御座います。
確認してみます。

Private Declare Function FtpSetCurrentDirectory Lib "wininet.dll" _
     Alias "FtpSetCurrentDirectoryA" _
     (ByVal hFtpSession As Long, ByRef lpszDirectory As String) As Long
                    ・
                    ・
                    ・
'StrConvを使用しない
lngRet = FtpSetCurrentDirectory(lngFtphnd,strFTPDir)

ってことですよね!?
これで試した結果も「12003(パスなし?)」が表示されてしまいます。

余談ですが、W系関数って何でしょうか?


FTP  2004-12-29 01:23:52  No: 118567

すいません。
読み落としがありました。

Private Declare Function FtpSetCurrentDirectory Lib "wininet.dll" _
     Alias "FtpSetCurrentDirectoryA" _
     (ByVal hFtpSession As Long, ByVal lpszDirectory As String) As Long
                    ・
                    ・
                    ・
'StrConvを使用しない
lngRet = FtpSetCurrentDirectory(lngFtphnd,strFTPDir)

で取得する事ができました。

レスをしてくれた皆様有難う御座いました。
解決です。


魔界の仮面弁士  2004-12-29 02:19:44  No: 118568

> 余談ですが、W系関数って何でしょうか?
失礼しました。あれでは説明不足ですよね。

文字列を扱うAPIの多くは、
  ANSI文字列(システム既定のコード/Shift_JIS)を使うバージョン
  Wide文字列(Unicode)を使うバージョン
の2種類を持っていますよね。
前者は関数名の最後がAで終わり、後者はWで終わります。

そして今回の場合、『Alias "FtpSetCurrentDirectoryA"』
という「最後がAで終わる関数」を使っていましたので、
それを指した発言でした。m(_ _)m
W系は、『Alias "FtpSetCurrentDirectoryW"』です。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加