質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

2回答

3902閲覧

WinAPI FTPダウンロードの完了検知

fearz

総合スコア7

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2016/07/09 07:28

編集2016/07/09 08:13

C++のWINAPIアプリケーションです。
非同期(WININET_API_FLAG_ASYNC)で接続したFTPセッションで、
FtpFileGet()でファイルをダウンロードしようとしています。
そこで、ダウンロード終了の検知ができずに困っております

InternetSetStatusCallback()で指定するコールバック関数で、

1 : INTERNET_STATUS_HANDLE_CREATED
2 : INTERNET_STATUS_RESPONSE_RECEIVEDでプログレス
3 : INTERNET_STATUS_REQUEST_COMPLETE

の順番かと予想していましたが、実際は1.で止まっています。
ファイルはダウンロードされて中身も正しいようです。
CREATEDを以て完了と判断してよいものか、
名前からするとそうではない気もするため悩んでいます。

本来はどの順番で来るものか、
ドキュメントも調べてみたのですが見つけることができませんでした。

セオリーとしてダウンロード完了をどのように判断すればよいか、
ご存じの方がいらっしゃいましたらご教授頂けないでしょうか

現状の、接続からコールバックまわりのコードをシンプルにしたものです。
実際にはダウンロード前に一覧取得していますのでファイルを次々とダウンロードする処理となります。

C++

1HINTERNET hnet = NULL; 2HINTERNET hftp = NULL; 3u32 dlsize = 100; 4u32 dlsize_cur = 0; 5 6void CALLBACK ftp_callback 7( 8 HINTERNET hnet, 9 DWORD dw_context, 10 DWORD dw_status, 11 LPVOID status_info, 12 DWORD status_info_len 13){ 14 switch( dw_status ) 15 { 16 case INTERNET_STATUS_HANDLE_CREATED: 17 { 18 if( app_status == 接続中 ) 19 { 20 LPINTERNET_ASYNC_RESULT result = (LPINTERNET_ASYNC_RESULT) status_info; 21 hftp = (HINTERNET) result->dwResult; 22 } 23 break; 24 } 25 case INTERNET_STATUS_REQUEST_COMPLETE: 26 { 27 if( app_status == 接続中 ) 28 { 29 // ※ここには来る 30 download_core(); 31 } 32 break; 33 } 34 case INTERNET_STATUS_RESPONSE_RECEIVED: 35 { 36 // ※ここに来ない 37 if( app_status == ダウンロード中 ) 38 { 39 LPDWORD bytes = (LPDWORD)status_info; 40 if( dlsize < *bytes ) dlsize = *bytes; 41 42 if( dlsize >= dlsize_cur ) 43 { 44 // ファイルのサイズ分ダウンロードされたので、 45 // ダウンロード完了とする。 46 // ...次のファイルダウンロード処理へ... 47 } 48 } 49 break; 50 } 51 } 52} 53 54// ダウンロード指示 55void download() 56{ 57 hnet = InternetOpen( 58 "ftp_client", 59 INTERNET_OPEN_TYPE_DIRECT, 60 NULL, 61 NULL, 62 WININET_API_FLAG_ASYNC 63 ); 64 if( hnet==NULL ) return エラー; 65 66 // コールバック登録 67 InternetSetStatusCallback( 68 hnet, 69 (INTERNET_STATUS_CALLBACK)&ftp_callback 70 ); 71 72 hftp = InternetConnect 73 ( 74 hnet, 75 "xx.xx.xx.xx", 76 INTERNET_DEFAULT_FTP_PORT, 77 NULL, 78 NULL, 79 INTERNET_SERVICE_FTP, 80 NULL, 81 (DWORD)&context 82 ); 83 if( hftp != NULL ) 84 { 85 download_core(); 86 } 87 else if( GetLastError()==ERROR_IO_PENDING ) app_status = 接続中 88 else { return 接続エラー } 89} 90 91void download_core() 92{ 93 if( ! hftp ) return; 94 if( FtpGetFile( 95 hftp, 96 "filename.txt", 97 "C:\\test\\test.txt", 98 false, 99 FILE_ATTRIBUTE_NORMAL, 100 FTP_TRANSFER_TYPE_BINARY, 101 NULL 102 ) == FALSE ){ 103 エラー処理 104 } 105 app_status = ダウンロード中 106 107 // ※ここまでは来る 108 // 上記メソッド実行時に、INTERNET_STATUS_HANDLE_CREATED 109 // を受け取り、ファイルも出来上がっているが、 110 // その他のイベントが来ない 111}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KoichiSugiyama

2016/07/09 07:44

コールバック関数はどういうものを書かれたか、差し障りがなければコードを提示してもらった方がアドバイスしやすいです。
guest

回答2

0

以下のページは参考になりませんか。

Missing INTERNET_STATUS_REQUEST_COMPLETE callback after calling Wininet’s FtpOpenFile() in asynchronous mode

INTERNET_FLAG_RELOADが必要なのかな?
ダメでしたらすみません。

投稿2016/07/18 20:30

phoenix3430025

総合スコア135

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

うろ覚えで申し訳ないですが、非同期通信の場合、INTERNET_STATUS_REQUEST_COMPLETEが来た段階で完了として良かったように記憶しています。なので、上記のコードではINTERNET_STATUS_HANDLE_CREATEDを受け取った段階でdownload_core()関数を実行できるのではないでしょうか。

投稿2016/07/09 13:17

KoichiSugiyama

総合スコア3041

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fearz

2016/07/11 02:17

ご回答ありがとうございます。 FtpGetFile()実行後は、INTERNET_STATUS_HANDLE_CREATEDしか受け取っておらず、 INTERNET_STATUS_REQUEST_COMPLETEは来ませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問