「Win32/64ネットワーク開発 003 wininetを使ったftp通信」の版間の差分
(→概要) |
編集の要約なし |
||
(同じ利用者による、間の5版が非表示) | |||
3行目: | 3行目: | ||
前の記事:[[Win32/64ネットワーク開発 002 wininetを使ったhttp通信]] | 前の記事:[[Win32/64ネットワーク開発 002 wininetを使ったhttp通信]] | ||
次の記事: | 次の記事:[[Win32/64ネットワーク開発 004 winsockを使ったhttp通信]] | ||
== '''概要''' == | == '''概要''' == | ||
35行目: | 35行目: | ||
URLを指定してhttp通信をするときは、InternetOpenUrl関数を使いましたが、FTP通信をするときはInternetConnect関数を使います。 | URLを指定してhttp通信をするときは、InternetOpenUrl関数を使いましたが、FTP通信をするときはInternetConnect関数を使います。 | ||
=== InternetConnect === | |||
<span style="color:darkred;font-weight:bold">■InternetConnect(HINTERNET, LPCWSTR, INTERNET_PORT, LPCWSTR, LPCWSTR, DWORD, DWORD, DWORD_PTR)</span> | <span style="color:darkred;font-weight:bold">■InternetConnect(HINTERNET, LPCWSTR, INTERNET_PORT, LPCWSTR, LPCWSTR, DWORD, DWORD, DWORD_PTR)</span> | ||
78行目: | 78行目: | ||
返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。一瞬なんのことをいっているかわからない説明だったと思いますが、DWORD dwContext=123(関数はDWORD_PTRの形式を必要としているので、&dwContextのように設定します)のように特定の識別値を与えることで、このあと使う関数で、この値によって複数の通信を切り分けて使うのに利用する目的で準備されている仕組みです。wininetを使うときにそこまで複雑な通信をするとは思えませんが、winsockなどで通信するときも、こういった複数のハンドル値を管理するうまい仕組みが必要だという予備知識にもなるかと思います。切り分けをするためにもこういった使い方をする手法があるということくらいは頭の隅においておいたほうがいいかもしれません。この仕組みを使わないで、適当に0と設定しておいてもいいわけです。 | 返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。一瞬なんのことをいっているかわからない説明だったと思いますが、DWORD dwContext=123(関数はDWORD_PTRの形式を必要としているので、&dwContextのように設定します)のように特定の識別値を与えることで、このあと使う関数で、この値によって複数の通信を切り分けて使うのに利用する目的で準備されている仕組みです。wininetを使うときにそこまで複雑な通信をするとは思えませんが、winsockなどで通信するときも、こういった複数のハンドル値を管理するうまい仕組みが必要だという予備知識にもなるかと思います。切り分けをするためにもこういった使い方をする手法があるということくらいは頭の隅においておいたほうがいいかもしれません。この仕組みを使わないで、適当に0と設定しておいてもいいわけです。 | ||
=== FtpSetCurrentDirectory === | |||
<span style="color:darkred;font-weight:bold">■FtpSetCurrentDirectory(HINTERNET, LPCWSTR)</span> | <span style="color:darkred;font-weight:bold">■FtpSetCurrentDirectory(HINTERNET, LPCWSTR)</span> | ||
92行目: | 92行目: | ||
=== FtpGetCurrentDirectory === | |||
<span style="color:darkred;font-weight:bold">■FtpGetCurrentDirectory(HINTERNET, LPCWSTR)</span> | <span style="color:darkred;font-weight:bold">■FtpGetCurrentDirectory(HINTERNET, LPCWSTR)</span> | ||
116行目: | 116行目: | ||
DWORD DWORDcontext2 = 2; | DWORD DWORDcontext2 = 2; | ||
DWORD DWORDcontext3 = 3; | DWORD DWORDcontext3 = 3; | ||
DWORD | |||
DWORD | DWORD DWORDsizeHigh = 0; | ||
DWORD | DWORD DWORDsizeLow = 0; | ||
DWORD DWORDwritesize = 0; | |||
FtpCreateDirectory(HINTERNEThost, L"NewFolder230101011111"); | FtpCreateDirectory(HINTERNEThost, L"NewFolder230101011111"); | ||
FtpRemoveDirectory(HINTERNEThost, L"NewFolder230101011111"); | FtpRemoveDirectory(HINTERNEThost, L"NewFolder230101011111"); | ||
132行目: | 134行目: | ||
FtpDeleteFile(HINTERNEThost, L"File230101011111.lzh"); | FtpDeleteFile(HINTERNEThost, L"File230101011111.lzh"); | ||
HINTERNET HINTERNETopen = FtpOpenFile(HINTERNEThost, L"Test_SJIS.css", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, (DWORD_PTR)&DWORDcontext1); | HINTERNET HINTERNETopen = FtpOpenFile(HINTERNEThost, L"Test_SJIS.css", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, (DWORD_PTR)&DWORDcontext1); | ||
DWORDsizeLow = FtpGetFileSize(HINTERNETopen, (LPDWORD)&DWORDsizeHigh); | |||
DWORD DWORDBufSize = 1024; | DWORD DWORDBufSize = 1024; | ||
141行目: | 143行目: | ||
char* pchOpenFileStr = new char[DWORDBufSize + 1]; | char* pchOpenFileStr = new char[DWORDBufSize + 1]; | ||
while(1){ | while(1){ | ||
BOOL bResult = InternetReadFile(HINTERNETopen, pchOpenFileStr, DWORDBufSize, & | BOOL bResult = InternetReadFile(HINTERNETopen, pchOpenFileStr, DWORDBufSize, &DWORDcontext2); | ||
pchOpenFileStr[ | pchOpenFileStr[DWORDcontext2] = '\0'; | ||
if (DWORDcontext4 == 0) { | if (DWORDcontext4 == 0) { | ||
break; | break; | ||
164行目: | 166行目: | ||
INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0); | INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0); | ||
FtpSetCurrentDirectory(HINTERNEThost, L"/public_html/www.yo-net.jp/"); | FtpSetCurrentDirectory(HINTERNEThost, L"/public_html/www.yo-net.jp/"); | ||
HINTERNET HINTERNETopen = FtpOpenFile(HINTERNEThost, L"Test_SJIS.css", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, (DWORD_PTR)& | HINTERNET HINTERNETopen = FtpOpenFile(HINTERNEThost, L"Test_SJIS.css", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, (DWORD_PTR)&DWORDcontext3); | ||
//sjisのcssファイルをUTF-8に変換する処理。 | //sjisのcssファイルをUTF-8に変換する処理。 | ||
183行目: | 185行目: | ||
} | } | ||
InternetWriteFile(HINTERNETopen, stringutf8String.c_str(), stringutf8String.size() - 1, & | InternetWriteFile(HINTERNETopen, stringutf8String.c_str(), stringutf8String.size() - 1, &DWORDwritesize); | ||
delete[] pwchutf16String; | delete[] pwchutf16String; | ||
190行目: | 192行目: | ||
=== FtpCreateDirectory === | |||
<span style="color:darkred;font-weight:bold">■FtpCreateDirectory(HINTERNET, LPCWSTR)</span> | <span style="color:darkred;font-weight:bold">■FtpCreateDirectory(HINTERNET, LPCWSTR)</span> | ||
203行目: | 206行目: | ||
=== FtpRemoveDirectory === | |||
<span style="color:darkred;font-weight:bold">■FtpRemoveDirectory(HINTERNET, LPCWSTR)</span> | <span style="color:darkred;font-weight:bold">■FtpRemoveDirectory(HINTERNET, LPCWSTR)</span> | ||
216行目: | 220行目: | ||
=== FtpPutFile === | |||
<span style="color:darkred;font-weight:bold">■FtpPutFile(HINTERNET, LPCWSTR, LPCWSTR, DWORD, DWORD_PTR)</span> | <span style="color:darkred;font-weight:bold">■FtpPutFile(HINTERNET, LPCWSTR, LPCWSTR, DWORD, DWORD_PTR)</span> | ||
244行目: | 249行目: | ||
=== FtpRenameFile === | |||
<span style="color:darkred;font-weight:bold">■FtpRenameFile(HINTERNET, LPCWSTR, LPCWSTR)</span> | <span style="color:darkred;font-weight:bold">■FtpRenameFile(HINTERNET, LPCWSTR, LPCWSTR)</span> | ||
262行目: | 268行目: | ||
=== FtpFindFirstFile === | |||
<span style="color:darkred;font-weight:bold">■FtpFindFirstFile(HINTERNET, LPCWSTR, LPWIN32_FIND_DATAW, DWORD, DWORD_PTR)</span> | <span style="color:darkred;font-weight:bold">■FtpFindFirstFile(HINTERNET, LPCWSTR, LPWIN32_FIND_DATAW, DWORD, DWORD_PTR)</span> | ||
276行目: | 283行目: | ||
'''第3引数:'''LPWIN32_FIND_DATAW lpFindFileData | '''第3引数:'''LPWIN32_FIND_DATAW lpFindFileData | ||
検索結果を返すLPWIN32_FIND_DATAW型構造体の変数。参照型として渡します。 | |||
'''第4引数:'''DWORD dwFlags | '''第4引数:'''DWORD dwFlags | ||
INTERNET_FLAG_HYPERLINK, INTERNET_FLAG_NEED_FILE, INTERNET_FLAG_NO_CACHE_WRITE, INTERNET_FLAG_RELOAD, INTERNET_FLAG_RESYNCHRONIZEといった検索処理についてのフラグを設定します。 | |||
:*INTERNET_FLAG_HYPERLINK | |||
:: ネットワークからアイテムを再読み込みするかどうかを決定するときに、有効期限時間がなく、サーバーから LastModified 時刻が返されない場合は、強制的に再読み込みを行う。 | |||
:*INTERNET_FLAG_NEED_FILE | |||
:: ファイルをキャッシュできない場合は、一時ファイルを作成します。 | |||
:*INTERNET_FLAG_NO_CACHE_WRITE | |||
:: 返されたエンティティをキャッシュに追加しません。 | |||
:*INTERNET_FLAG_RELOAD | |||
:: 要求されたファイル、オブジェクト、またはディレクトリ リストをキャッシュからではなく元のサーバーからダウンロードします。 | |||
:*INTERNET_FLAG_RESYNCHRONIZE | |||
:: 最後にダウンロードされてからリソースが変更された場合は、HTTP リソースを再読み込みします。 すべての FTP リソースが再読み込みされます。 | |||
284行目: | 315行目: | ||
返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。 | 返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。 | ||
=== FtpDeleteFile === | |||
<span style="color:darkred;font-weight:bold">■FtpDeleteFile(HINTERNET, LPCWSTR)</span> | |||
'''第1引数:'''HINTERNET hConnect | |||
InternetConnect関数で得られるHINTERNET型ハンドルです。 | |||
'''第2引数:'''LPCWSTR lpszFileName | |||
削除するファイルの名前の文字列を保持した配列変数の先頭を差す文字型のポインタです。 | |||
=== FtpOpenFile === | |||
<span style="color:darkred;font-weight:bold">■FtpOpenFile(HINTERNET, LPCWSTR, DWORD, DWORD, DWORD_PTR)</span> | |||
オープンした状態でFtpGetFileSizeとInternetReadFileとInternetWriteFile関数が使えます。戻り値にはHINTERNET型のインスタンスハンドルを取得できます。 | |||
'''第1引数:'''HINTERNET hConnect | |||
InternetConnect関数で得られるHINTERNET型ハンドルです。 | |||
'''第2引数:'''LPCWSTR lpszFileName | |||
ファイルオープンするファイルのファイル名を保持した配列変数の先頭を差す文字型のポインタです。 | |||
'''第3引数:'''DWORD dwAccess | |||
ファイルアクセスについての指定。このパラメーターはGENERIC_READまたはGENERIC_WRITEを指定できます。両方を指定することはできません。 | |||
'''第4引数:'''DWORD dwFlags | |||
ファイルの通信方式を定義するフラグです。FTP_TRANSFER_TYPE_BINARY(2)とFTP_TRANSFER_TYPE_ASCII(1)を主に指定します。 | |||
'''第5引数:'''DWORD_PTR dwContext | |||
返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。 | |||
=== FtpGetFileSize === | |||
<span style="color:darkred;font-weight:bold">■FtpGetFileSize(HINTERNET, LPCWSTR)</span> | |||
'''第1引数:'''HINTERNET hConnect | |||
FtpOpenFile関数で得られるHINTERNET型ハンドルです。 | |||
'''第2引数:'''LPDWORD lpdwFileSizeHigh | |||
要求されたFTPリソースのファイルサイズの上位符号なしlong整数へのポインター。参照で渡します。ファイルサイズが4GByteを超えるような場合だけ第2引数で0以外の値を得ることができます。 | |||
=== InternetWriteFile === | |||
<span style="color:darkred;font-weight:bold">■InternetWriteFile(HINTERNET, LPCVOID, DWORD, LPDWORD)</span> | |||
'''第1引数:'''HINTERNET hConnect | |||
FtpOpenFile関数で得られるHINTERNET型ハンドルです。 | |||
'''第2引数:'''LPCVOID lpBuffer | |||
ファイルに書き込まれる、文字列の先頭アドレスです。 | |||
'''第3引数:'''DWORD dwNumberOfBytesToWrite | |||
ファイルに書き込まれるバイト数。 | |||
'''第4引数:'''LPDWORD lpdwNumberOfBytesWritten | |||
ファイルに書き込まれたバイト数を受け取る変数です。参照で渡します。 | |||
FTPコマンドは沢山ありますので、それも実行できないと都合が悪いわけです。そのための関数として以下のようなものもあります。上記のプログラムの続きとしてコードを記述しています。 | |||
<syntaxhighlight lang="cpp"> | |||
DWORD DWORDcontext4 = 4; | |||
HINTERNET HINTERNETftp; | |||
char buffer[1025]; | |||
DWORD bytesRead = 0; | |||
FtpCommand(HINTERNEThost, TRUE, FTP_TRANSFER_TYPE_ASCII, L"LIST", DWORDcontext4, &HINTERNETftp); | |||
InternetReadFile(HINTERNETftp, buffer, sizeof(buffer), &bytesRead); | |||
</syntaxhighlight> | |||
例えば"LIST"というコマンドを実効するときは上記のようにします。HINTERNET型の変数の参照を第6変数にとるFtpCommand関数で | |||
実行した結果を得るには第6引数のHINTERNET型変数に受け取っているので、これをInternetReadFile関数の第1引数にすることで文字列として応答結果を得ることができます。 | |||
ただし、管理人が使っている環境ではxreaのftpサーバからはwininetライブラリではコマンド完了の応答が得られず、FtpCommand関数を使うたびに一度、接続を切って、またカレントディレクトリの調整をして再開しなければならないような状態になりました。ftpサーバの仕様によっては、FtpCommand関数が使えないということなので、注意が必要かもしれません。結局は自分でWinsockレベルで通信をするプログラムを作らないとダメなのかもしれません。wininetライブラリは簡易的なプログラムの範囲で、関係者内でしか使うことはできないかもしれません。広く配布しておいて使えない人がいるという状態になるのは避けたいものです。 | |||
=== FtpCommand === | |||
<span style="color:darkred;font-weight:bold">■FtpCommand(HINTERNET, BOOL, LPCWSTR, DWORD_PTR, HINTERNET)</span> | |||
'''第1引数:'''HINTERNET hConnect | |||
FtpOpenFile関数で得られるHINTERNET型ハンドルです。 | |||
'''第2引数:'''BOOL fExpectResponse | |||
データ接続が必要なコマンドである場合はTRUE。 | |||
'''第3引数:'''DWORD dwFlags | |||
ファイルの通信方式を定義するフラグです。FTP_TRANSFER_TYPE_BINARY(2)とFTP_TRANSFER_TYPE_ASCII(1)を主に指定します。 | |||
'''第4引数:'''LPCWSTR lpszCommand | |||
コマンドの文字列を指定します。大体ASCIIコードの範囲の文字列であるはずです。それでもワイド文字列版の関数はあります。 | |||
'''第5引数:'''DWORD_PTR dwContext | |||
返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。 | |||
'''第6引数:'''HINTERNET *phFtpCommand | |||
コマンドで得られる結果を取得するHINTERNET型ハンドルです。このハンドルを使って、次のステップでInternetReadFile関数を使って応答の文字列を得ることが出来ます。 | |||
292行目: | 461行目: | ||
前の記事:[[Win32/64ネットワーク開発 002 wininetを使ったhttp通信]] | 前の記事:[[Win32/64ネットワーク開発 002 wininetを使ったhttp通信]] | ||
次の記事: | 次の記事:[[Win32/64ネットワーク開発 004 winsockを使ったhttp通信]] | ||
[[Win32/64 ネットワーク処理開発]]へ戻る。 | [[Win32/64 ネットワーク処理開発]]へ戻る。 |
2023年12月3日 (日) 17:48時点における最新版
前の記事:Win32/64ネットワーク開発 002 wininetを使ったhttp通信
次の記事:Win32/64ネットワーク開発 004 winsockを使ったhttp通信
概要
wininet.Libやwininet.hのインクルードについては前の記事の通り、同じように設定する必要があります。
まずは、ホスト名やユーザID、パスワード、接続時に最初に表示するディレクトリ名を聞いてくるようなインタフェースを持たない固定値での接続を試してみましょう。接続して、FTPでカレントディレクトリを設定してカレントディレクトリが今何かを返してくれるとこまでのプログラムを書いてみます。以下のとおりです。
HINTERNET HINTERNETinet = InternetOpen(L"yo-net.jp ftp", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
HINTERNET HINTERNEThost = InternetConnect(
HINTERNETinet,
L"ftp.xxxx.com", INTERNET_DEFAULT_FTP_PORT,
L"ftp_user_name", L"ftp_user_password",
INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
FtpSetCurrentDirectory(HINTERNEThost, L"/");
DWORD DWORDsize = 0;
FtpGetCurrentDirectory(HINTERNEThost, NULL, &DWORDsize);
wchar_t* pwchCurrentDir = new wchar_t[DWORDsize/sizeof(wchar_t)];
FtpGetCurrentDirectory(HINTERNEThost, pwchCurrentDir, &DWORDsize);
上記のプログラムにより、pwchCurrentDirにFTP接続したときの現在のディレクトリを取得できます。
InternetOpen関数についての説明はコチラのリンクから確認して下さい。FTP通信をするときはホスト名やログイン名を使うので第2引数のフラグはINTERNET_OPEN_TYPE_DIRECTを指定します。
URLを指定してhttp通信をするときは、InternetOpenUrl関数を使いましたが、FTP通信をするときはInternetConnect関数を使います。
InternetConnect
■InternetConnect(HINTERNET, LPCWSTR, INTERNET_PORT, LPCWSTR, LPCWSTR, DWORD, DWORD, DWORD_PTR)
第1引数:HINTERNET hInternet
InternetOpen関数によって得られる、HINTERNETハンドルです。
第2引数:LPCWSTR lpszServerName
FTPサーバへのアドレスまたはホスト名を文字列で指定します。
第3引数:INTERNET_PORT nServerPort
wininet.hで INTERNET_DEFAULT_FTP_PORT には通常FTPで使われるポート番号21が設定されていますので、このキーワードを使うのが普通ですが、違うPORT番号でサーバ側がFTP通信をリスニング、受け入れ待ちをしている場合は、特定の番号を指定する必要があります。DWORD型の別名がINTERNET_PROTとなっています。0~65535の間の16bitの整数値です。
第4引数:LPCWSTR lpszUserName
FTPログインをするときのID名です。
第5引数:LPCWSTR lpszPassword
FTPログインをするときのID名に対して関連付けられたパスワード文字列です。
第6引数:DWORD dwService
アクセスするサービスの種類です。FTP(INTERNET_SERVICE_FTP)とGOPHER(INTERNET_SERVICE_GOPHER)とHTTP(INTERNET_SERVICE_HTTP)があります。FTP通信時は通常はFTPを指定します。
第7引数:DWORD dwFlags
INTERNET_FLAG_PASSIVE(0x0800 0x0000)を指定します。
第8引数:DWORD_PTR dwContext
返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。一瞬なんのことをいっているかわからない説明だったと思いますが、DWORD dwContext=123(関数はDWORD_PTRの形式を必要としているので、&dwContextのように設定します)のように特定の識別値を与えることで、このあと使う関数で、この値によって複数の通信を切り分けて使うのに利用する目的で準備されている仕組みです。wininetを使うときにそこまで複雑な通信をするとは思えませんが、winsockなどで通信するときも、こういった複数のハンドル値を管理するうまい仕組みが必要だという予備知識にもなるかと思います。切り分けをするためにもこういった使い方をする手法があるということくらいは頭の隅においておいたほうがいいかもしれません。この仕組みを使わないで、適当に0と設定しておいてもいいわけです。
FtpSetCurrentDirectory
■FtpSetCurrentDirectory(HINTERNET, LPCWSTR)
第1引数:HINTERNET hConnect
InternetConnect関数で得られるHINTERNET型ハンドルです。
第2引数:LPCWSTR lpszDirectory
接続しているFTP通信で、現在のディレクトリとして設定したい文字列を設定します。FTPルートディレクトリからの絶対パスである必要があります。
FtpGetCurrentDirectory
■FtpGetCurrentDirectory(HINTERNET, LPCWSTR)
第1引数:HINTERNET hConnect
InternetConnect関数で得られるHINTERNET型ハンドルです。
第2引数:LPWSTR lpszCurrentDirectory
接続しているFTP通信で、現在のディレクトリがどういう名前なのか取得したい文字列取得領域を設定します。FTPルートディレクトリからの絶対パスが取得できます。文字列の確保領域が取得できる文字列より小さいあるいはNULLである場合は、第3引数に必要な文字列バイト長が返却されます。UTF-16で受け取ろうとする場合は、文字列の長さの2倍となっています。
第3引数:LPDWORD lpdwCurrentDirectory
取得した文字列の長さを受け取るWORD型の変数へのアドレスを指定します。
DWORD DWORDcontext0 = 0;
DWORD DWORDcontext1 = 1;
DWORD DWORDcontext2 = 2;
DWORD DWORDcontext3 = 3;
DWORD DWORDsizeHigh = 0;
DWORD DWORDsizeLow = 0;
DWORD DWORDwritesize = 0;
FtpCreateDirectory(HINTERNEThost, L"NewFolder230101011111");
FtpRemoveDirectory(HINTERNEThost, L"NewFolder230101011111");
FtpPutFile(HINTERNEThost, //FTPのインターネットハンドル
L"File230101011111.lzh", //アップロードするファイル
L"/public_html/www.yo-net.jp/File230101011111.lzh", //アップロード先のパス付ファイル名
FTP_TRANSFER_TYPE_BINARY, //バイナリファイルとしてダウンロード
(DWORD_PTR)&DWORDcontext0);
FtpRenameFile(HINTERNEThost, L"File230101011111.lzh", L"File230101011112.lzh");
FtpRenameFile(HINTERNEThost, L"File230101011112.lzh", L"File230101011111.lzh");
WIN32_FIND_DATA WIN32_FIND_DATAfind;
FtpFindFirstFile(HINTERNEThost, L"File230101011111.lzh", &WIN32_FIND_DATAfind, 0, 0);
FtpDeleteFile(HINTERNEThost, L"File230101011111.lzh");
HINTERNET HINTERNETopen = FtpOpenFile(HINTERNEThost, L"Test_SJIS.css", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, (DWORD_PTR)&DWORDcontext1);
DWORDsizeLow = FtpGetFileSize(HINTERNETopen, (LPDWORD)&DWORDsizeHigh);
DWORD DWORDBufSize = 1024;
DWORD DWORDTotal = 0;
HGLOBAL HGLOBALMem;
HGLOBALMem = GlobalAlloc(GHND, 1);
char* pchOpenFileStrTotal = nullptr;
char* pchOpenFileStr = new char[DWORDBufSize + 1];
while(1){
BOOL bResult = InternetReadFile(HINTERNETopen, pchOpenFileStr, DWORDBufSize, &DWORDcontext2);
pchOpenFileStr[DWORDcontext2] = '\0';
if (DWORDcontext4 == 0) {
break;
}
DWORDTotal += DWORDcontext4;
HGLOBALMem = GlobalReAlloc(HGLOBALMem, DWORDTotal + 1, GMEM_MOVEABLE);
pchOpenFileStrTotal = (char*)GlobalLock(HGLOBALMem);
strcat_s(pchOpenFileStrTotal, DWORDTotal + 1, pchOpenFileStr);
}
int iSize = MultiByteToWideChar(932, 0U, pchOpenFileStrTotal, -1, nullptr, 0);
wchar_t* pwchOpenFileStr = new wchar_t[iSize];
MultiByteToWideChar(932, 0U, pchOpenFileStrTotal, -1, pwchOpenFileStr, iSize);
InternetCloseHandle(HINTERNEThost);
InternetCloseHandle(HINTERNETinet);
HINTERNETinet = InternetOpen(L"yo-net.jp ftp", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
HINTERNEThost = InternetConnect(
HINTERNETinet,
L"ftp.xxxx.com", INTERNET_DEFAULT_FTP_PORT,
L"ftp_user_name", L"ftp_user_password",
INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
FtpSetCurrentDirectory(HINTERNEThost, L"/public_html/www.yo-net.jp/");
HINTERNET HINTERNETopen = FtpOpenFile(HINTERNEThost, L"Test_SJIS.css", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, (DWORD_PTR)&DWORDcontext3);
//sjisのcssファイルをUTF-8に変換する処理。
wchar_t* pwchutf16String = nullptr;
int utf16Length = MultiByteToWideChar(932, 0, pchOpenFileStrTotal, -1, NULL, 0);
if (utf16Length > 0) {
pwchutf16String = new wchar_t[utf16Length];
MultiByteToWideChar(932, 0, pchOpenFileStrTotal, -1, pwchutf16String, utf16Length);
}
char* pchutf8String = nullptr;
int iutf8Length = WideCharToMultiByte(CP_UTF8, 0, pwchutf16String, -1, nullptr, 0, nullptr, nullptr);
pchutf8String = new char[iutf8Length]; // NULL 終端文字を含めないサイズに修正
std::string stringutf8String(iutf8Length, 0);
if (iutf8Length > 0) {
WideCharToMultiByte(CP_UTF8, 0, pwchutf16String, -1, &stringutf8String[0], iutf8Length, nullptr, nullptr);
stringutf8String[iutf8Length - 1] = '\0';
}
InternetWriteFile(HINTERNETopen, stringutf8String.c_str(), stringutf8String.size() - 1, &DWORDwritesize);
delete[] pwchutf16String;
delete[] pchutf8String;
FtpCreateDirectory
■FtpCreateDirectory(HINTERNET, LPCWSTR)
第1引数:HINTERNET hConnect
InternetConnect関数で得られるHINTERNET型ハンドルです。
第2引数:LPCWSTR lpszDirectory
作成するディレクトリの名前の文字列を保持した配列変数の先頭を差す文字型のポインタです。
FtpRemoveDirectory
■FtpRemoveDirectory(HINTERNET, LPCWSTR)
第1引数:HINTERNET hConnect
InternetConnect関数で得られるHINTERNET型ハンドルです。
第2引数:LPCWSTR lpszDirectory
削除するディレクトリの名前の文字列を保持した配列変数の先頭を差す文字型のポインタです。
FtpPutFile
■FtpPutFile(HINTERNET, LPCWSTR, LPCWSTR, DWORD, DWORD_PTR)
第1引数:HINTERNET hConnect
InternetConnect関数で得られるHINTERNET型ハンドルです。
第2引数:LPCWSTR lpszLocalFile
アップロードするファイル名の文字列を保持した配列変数の先頭を差す文字型のポインタです。
第3引数:LPCWSTR lpszNewRemoteFile
アップロードしたファイルをアップロード先でのファイル名を指定したルートディレクトリからのファイルパスを含めた文字列を保持した配列変数の先頭を差す文字型のポインタです。
第4引数:DWORD dwFlags
アップロードするファイルの通信方式を定義するフラグです。FTP_TRANSFER_TYPE_BINARY(2)とFTP_TRANSFER_TYPE_ASCII(1)を主に指定します。FTP_TRANSFER_TYPE_BINARYの場合はファイルはそのまま送られ、FTP_TRANSFER_TYPE_ASCIIの場合は改行コードを変換する処理が入ります。CR+LFをLFだけにする変換を行います。現代においては、サーバー側に配置されるテキストがCR+LFの形式であっても問題なく表示・プログラム実行処理されるので、変換する必要はなくなってきています。ただし、変換してアップロードしたファイルがあって、取得する場合にまた変換する必要があったりはしますので、ファイルの扱い方の状況次第では必要になってきます。正しくない通信によって、改行コードがごちゃごちゃしてきている可能性があります。WindowsではCR+LFにUnix系ではLFにという変換を管理する必要があります。作るならば、そういったことを手助けするようなFTPツールであるべきですね。
第5引数:DWORD_PTR dwContext
返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。一瞬なんのことをいっているかわからない説明だったと思いますが、DWORD dwContext=123(関数はDWORD_PTRの形式を必要としているので、&dwContextのように設定します)のように特定の識別値を与えることで、このあと使う関数で、この値によって複数の通信を切り分けて使うのに利用する目的で準備されている仕組みです。wininetを使うときにそこまで複雑な通信をするとは思えませんが、winsockなどで通信するときも、こういった複数のハンドル値を管理するうまい仕組みが必要だという予備知識にもなるかと思います。切り分けをするためにもこういった使い方をする手法があるということくらいは頭の隅においておいたほうがいいかもしれません。この仕組みを使わないで、適当に0と設定しておいてもいいわけです。毎回同じことを書いてますので、以降では説明は省略しましょうかね。
FtpRenameFile
■FtpRenameFile(HINTERNET, LPCWSTR, LPCWSTR)
第1引数:HINTERNET hConnect
InternetConnect関数で得られるHINTERNET型ハンドルです。
第2引数:LPCWSTR lpszExisting
変更するファイルの元の名前の文字列を保持した配列変数の先頭を差す文字型のポインタです。
第3引数:LPCWSTR lpszNew
変更するファイルの変更後の名前の文字列を保持した配列変数の先頭を差す文字型のポインタです。
FtpFindFirstFile
■FtpFindFirstFile(HINTERNET, LPCWSTR, LPWIN32_FIND_DATAW, DWORD, DWORD_PTR)
第1引数:HINTERNET hConnect
InternetConnect関数で得られるHINTERNET型ハンドルです。
第2引数:LPCWSTR lpszSearchFile
検索するファイル名の文字列を保持した配列変数の先頭を差す文字型のポインタです。
第3引数:LPWIN32_FIND_DATAW lpFindFileData
検索結果を返すLPWIN32_FIND_DATAW型構造体の変数。参照型として渡します。
第4引数:DWORD dwFlags
INTERNET_FLAG_HYPERLINK, INTERNET_FLAG_NEED_FILE, INTERNET_FLAG_NO_CACHE_WRITE, INTERNET_FLAG_RELOAD, INTERNET_FLAG_RESYNCHRONIZEといった検索処理についてのフラグを設定します。
- INTERNET_FLAG_HYPERLINK
- ネットワークからアイテムを再読み込みするかどうかを決定するときに、有効期限時間がなく、サーバーから LastModified 時刻が返されない場合は、強制的に再読み込みを行う。
- INTERNET_FLAG_NEED_FILE
- ファイルをキャッシュできない場合は、一時ファイルを作成します。
- INTERNET_FLAG_NO_CACHE_WRITE
- 返されたエンティティをキャッシュに追加しません。
- INTERNET_FLAG_RELOAD
- 要求されたファイル、オブジェクト、またはディレクトリ リストをキャッシュからではなく元のサーバーからダウンロードします。
- INTERNET_FLAG_RESYNCHRONIZE
- 最後にダウンロードされてからリソースが変更された場合は、HTTP リソースを再読み込みします。 すべての FTP リソースが再読み込みされます。
第5引数:DWORD_PTR dwContext
返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。
FtpDeleteFile
■FtpDeleteFile(HINTERNET, LPCWSTR)
第1引数:HINTERNET hConnect
InternetConnect関数で得られるHINTERNET型ハンドルです。
第2引数:LPCWSTR lpszFileName
削除するファイルの名前の文字列を保持した配列変数の先頭を差す文字型のポインタです。
FtpOpenFile
■FtpOpenFile(HINTERNET, LPCWSTR, DWORD, DWORD, DWORD_PTR)
オープンした状態でFtpGetFileSizeとInternetReadFileとInternetWriteFile関数が使えます。戻り値にはHINTERNET型のインスタンスハンドルを取得できます。
第1引数:HINTERNET hConnect
InternetConnect関数で得られるHINTERNET型ハンドルです。
第2引数:LPCWSTR lpszFileName
ファイルオープンするファイルのファイル名を保持した配列変数の先頭を差す文字型のポインタです。
第3引数:DWORD dwAccess
ファイルアクセスについての指定。このパラメーターはGENERIC_READまたはGENERIC_WRITEを指定できます。両方を指定することはできません。
第4引数:DWORD dwFlags
ファイルの通信方式を定義するフラグです。FTP_TRANSFER_TYPE_BINARY(2)とFTP_TRANSFER_TYPE_ASCII(1)を主に指定します。
第5引数:DWORD_PTR dwContext
返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。
FtpGetFileSize
■FtpGetFileSize(HINTERNET, LPCWSTR)
第1引数:HINTERNET hConnect
FtpOpenFile関数で得られるHINTERNET型ハンドルです。
第2引数:LPDWORD lpdwFileSizeHigh
要求されたFTPリソースのファイルサイズの上位符号なしlong整数へのポインター。参照で渡します。ファイルサイズが4GByteを超えるような場合だけ第2引数で0以外の値を得ることができます。
InternetWriteFile
■InternetWriteFile(HINTERNET, LPCVOID, DWORD, LPDWORD)
第1引数:HINTERNET hConnect
FtpOpenFile関数で得られるHINTERNET型ハンドルです。
第2引数:LPCVOID lpBuffer
ファイルに書き込まれる、文字列の先頭アドレスです。
第3引数:DWORD dwNumberOfBytesToWrite
ファイルに書き込まれるバイト数。
第4引数:LPDWORD lpdwNumberOfBytesWritten
ファイルに書き込まれたバイト数を受け取る変数です。参照で渡します。
FTPコマンドは沢山ありますので、それも実行できないと都合が悪いわけです。そのための関数として以下のようなものもあります。上記のプログラムの続きとしてコードを記述しています。
DWORD DWORDcontext4 = 4;
HINTERNET HINTERNETftp;
char buffer[1025];
DWORD bytesRead = 0;
FtpCommand(HINTERNEThost, TRUE, FTP_TRANSFER_TYPE_ASCII, L"LIST", DWORDcontext4, &HINTERNETftp);
InternetReadFile(HINTERNETftp, buffer, sizeof(buffer), &bytesRead);
例えば"LIST"というコマンドを実効するときは上記のようにします。HINTERNET型の変数の参照を第6変数にとるFtpCommand関数で
実行した結果を得るには第6引数のHINTERNET型変数に受け取っているので、これをInternetReadFile関数の第1引数にすることで文字列として応答結果を得ることができます。
ただし、管理人が使っている環境ではxreaのftpサーバからはwininetライブラリではコマンド完了の応答が得られず、FtpCommand関数を使うたびに一度、接続を切って、またカレントディレクトリの調整をして再開しなければならないような状態になりました。ftpサーバの仕様によっては、FtpCommand関数が使えないということなので、注意が必要かもしれません。結局は自分でWinsockレベルで通信をするプログラムを作らないとダメなのかもしれません。wininetライブラリは簡易的なプログラムの範囲で、関係者内でしか使うことはできないかもしれません。広く配布しておいて使えない人がいるという状態になるのは避けたいものです。
FtpCommand
■FtpCommand(HINTERNET, BOOL, LPCWSTR, DWORD_PTR, HINTERNET)
第1引数:HINTERNET hConnect
FtpOpenFile関数で得られるHINTERNET型ハンドルです。
第2引数:BOOL fExpectResponse
データ接続が必要なコマンドである場合はTRUE。
第3引数:DWORD dwFlags
ファイルの通信方式を定義するフラグです。FTP_TRANSFER_TYPE_BINARY(2)とFTP_TRANSFER_TYPE_ASCII(1)を主に指定します。
第4引数:LPCWSTR lpszCommand
コマンドの文字列を指定します。大体ASCIIコードの範囲の文字列であるはずです。それでもワイド文字列版の関数はあります。
第5引数:DWORD_PTR dwContext
返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。
第6引数:HINTERNET *phFtpCommand
コマンドで得られる結果を取得するHINTERNET型ハンドルです。このハンドルを使って、次のステップでInternetReadFile関数を使って応答の文字列を得ることが出来ます。
前の記事:Win32/64ネットワーク開発 002 wininetを使ったhttp通信