• ベストアンサー

InternetReadFileを使ったファイルダウンロード

下のようなプログラムは、httpサーバから特定のファイルを ダウンロードすることが目的です。 (※referer, file名は仮のものです。) 試しに動かしてみて、転送速度が比較的速い場合には、一応問題なく ダウンロードすることができたのですが、転送速度が遅い場合には、 ファイルサイズがどんどん膨れ上がってしまいます。 問題は、InternetReadFileでブロックされることがないからだと 推測しましたが、情報が少なく困っています。 転送速度が遅い場合にも正常にダウンロードするにはどうしたら よいでしょうか? #include <windows.h> #include <wininet.h> #include <stdio.h> #include <stdlib.h> bool GetHttpFile(){   HINTERNET hInternet;   HINTERNET hFile;   char Buf[1000]; /* バッファ */   DWORD ReadSize;   BOOL bResult;   wchar_t szHead[] = TEXT("Referer:http://aaa.com/\r\n\r\n"); // ヘッダにRefererを追加する   FILE *fp;   bool ret;   /* 保存先ファイル作成/open */     fp = fopen("sample.zip", "wb");   if (fp == NULL){  /* ファイル作成/openに失敗 */     ret = false;        }else{ /* ファイル作成/openに成功 */     /* WININET初期化 */     hInternet = InternetOpen(       TEXT("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)"),       INTERNET_OPEN_TYPE_PRECONFIG,       NULL,       NULL,       0);        /* URLのオープン */     hFile = InternetOpenUrl(       hInternet,       TEXT("http://aaa.com/bbb.zip"),       szHead,       0,       INTERNET_FLAG_RELOAD,       0);        /* オープンしたURLからデータを(1000バイトずつ)読み込む */     for(;;){       ReadSize = 1000;          bResult = InternetReadFile(         hFile,         Buf,         1000,         &ReadSize);          /* 全て読み込んだらループを抜ける */       if(bResult && (ReadSize == 0)) break;              /* ファイルに書き込み */       fwrite(Buf, sizeof(char), 1000, fp);     }        /* 後処理 */     InternetCloseHandle(hFile);     InternetCloseHandle(hInternet);     fclose(fp);     ret = true;   }      return ret; } int main(){   if(GetHttpFile() == true){     printf("成功\n");   }else{     printf("失敗\n");   }      return 0; }

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

あくまで予想なので間違ってるかも ダウンロードの関数とか使ったことないし、処理もちらっとしか見てないけど、 1000バイトずつ)読み込むってので、1000バイト読めなかった場合の差分が増えているってことはない? 例えば500しか読めなかったら、残りの500が不定データとして格納されてその分最終的なDLサイズが増えているとか?

upanepa
質問者

お礼

ご回答ありがとうございます。 まさにその通りだと思われます。 fwriteの引数設定がよくないようでした。

その他の回答 (1)

  • x415f484f
  • ベストアンサー率71% (57/80)
回答No.1

私の環境で 30MB のファイルでテストしましたがサイズが膨らむ現象は再現しないので わからないのですが、気になるところがありましたので……。 >for(;;){ >ReadSize = 1000; ReadSize = 0; >/* ファイルに書き込み */ >fwrite(Buf, sizeof(char), 1000, fp); fwrite(Buf, sizeof(char), ReadSize, fp); としないと、TCP/IP のタイムアウトが原因でサイズが膨らむことはないのでしょうか?

upanepa
質問者

お礼

ご回答ありがとうございます。 おそらくご指摘の通りだと思われます。 InternetReadFileの最後の引数には、ダウンロードした byte数が入るようで、ご指摘の通りに修正してみました。 現在は帯域が大きく直ったか確かめられません。 正常にダウンロードできたことは確認しました。

関連するQ&A

  • InternetReadFile関数でHTMLデータをメモリに格納

    HTMLソースをメモリに格納したいのですが、 以下のように1000バイトずつデータをBuffに格納するのはできたのですが、 HTMLファイル全てのデータをメモリに格納する場合はどのようにしたらいいのでしょうか? char Buff[1000]; for(;;){  ReadSize = 1000;  bResult = InternetReadFile ( hFile, Buff, 1000, &ReadSize );  //全て読み込み終わるとループを抜ける  if( bResult && (ReadSize == 0) ) break;  Buff[ReadSize] = '\0'; }

  • InternetReadFileで大きいファイルが読み取れない

    InternetReadFileでウェブ上のファイルをローカルPCにコピーするプログラムが、ファイルサイズが大きくなると最後までコピーできません。具体的には1Mバイト以上のファイルの読み取りにおいて、150K~400Kバイトまでしか読み取ることができません。読み取られたバイト数(以下のプログラムでdwByteRead)が0になり、それ以降のデータを読み取れません。読み取られた総バイト数は読み取りバッファサイズ(以下のプログラムでREAD_BUF_SIZE)の整数倍ですが、その値は毎回異なります。(殆どの場合、150K~400Kバイト)dwByteReadが0なった後、10回再試行を行うルーチンを追加してみましたが、一旦0になるとそれ以降は復活することはなく効果無しでした。このプログラムは数10Kバイトまでの読み取りでは安定して動作しているので、プログラム自体の安定性は問題ないと思います。 InternetReadFileで1Mバイト以上のファイルを読み取ることに成功して方がいらっしゃいました、その方法をご教示ください。他の方法でも1Mバイト以上のファイルをhttpから取り込むことができる方法で結構です。 HINTERNET hSession = InternetOpen( "MyApp", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 ); if( hSession ){ HINTERNET hService = InternetOpenUrl( hSession, url, NULL, 0, 0, 0 ); if( hService ){ ... if( (fp=fopen(fName.c_str(), "wb")) != NULL ){ fwrite( lpBuffer, dwBytesRead, 1, fp ); while(true){ Byte lpBuffer[READ_BUF_SIZE+1]; DWORD dwBytesRead = READ_BUF_SIZE; InternetReadFile( hService, lpBuffer, READ_BUF_SIZE, &dwBytesRead ); if( dwBytesRead == 0 ) break; fwrite( lpBuffer, dwBytesRead, 1, fp ); } ...

  • WinInetのInternetOpenUrl関数が正常に動作しない。

    ネットワーク上のHTMLソースを取得しようとしています。InternetOpenUrl関数が動作せず、常にNULLが返ってきます。 環境は、WindowsXP、WindowsCE Platform Builder です。 void Get_HTML(){ HINTERNET hInternet; HINTERNET hFile; char Buff[1000]; DWORD ReadSize; BOOL bResult; //WinInetの初期化 char *agent ="WININET Sample Program"; hInternet = InternetOpen( (LPCWSTR)agent, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 ); if( hInternet == NULL ){ printf("InternetOpen Error \n"); } //ネット接続チェック if( InternetAttemptConnect(0) != ERROR_SUCCESS { printf("インターネットに接続できません。\n"); } else{ printf("インターネットに接続できる\n"); } //URLオープン char open_url="http://www.sample.com/sam1.html"; hFile = InternetOpenUrl( hInternet, (LPCWSTR)open_url, NULL, 0, INTERNET_FLAG_RELOAD, 0 ); printf("%s",(LPCWSTR)open_url); if( hFile == NULL ){ printf(" InternetOpenUrl ERROR \n"); } } InternetOpenUrl関数の戻り値がNULLになりReadを することが出来ません。 解決方法よろしくお願い致します。

  • jpgファイルのダウンロード

    WWWサーバー上にあるjpgファイルを指定してそれをダウンロードするプログラムをつくっています。 jpgファイルが作成されることはされるのですが、中身をみることができない状態になってしまいます。 どこが悪いのかわかる方がおられましたらご教授お願いします。 <ソースコード> #include <windows.h> #include <stdio.h> #include <wininet.h> int main(void) { HINTERNET hInet, hUrl; char szBuf[128], szUrl[128], *lpszSrc; DWORD dwRead, dwTotal = 0; HGLOBAL hMem; FILE *file; printf("URL---- "); gets(szUrl); hInet = InternetOpen(TEXT("neko"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if(hInet == NULL){ perror("オープンエラー\n"); return -2; } hUrl = InternetOpenUrl(hInet, szUrl, NULL, 0, 0, 0); if(hUrl == NULL){ perror("URLオープンエラー\n"); return -3; } hMem = GlobalAlloc(GHND, 1); lpszSrc = (char*)GlobalLock(hMem); while(1){ InternetReadFile(hUrl, szBuf, (DWORD)sizeof(szBuf)-1, &dwRead); szBuf[dwRead] = '\0'; if(dwRead == 0){ break; } dwTotal += dwRead; hMem = GlobalReAlloc(hMem, dwTotal+1, GMEM_MOVEABLE); lpszSrc = (char*)GlobalLock(hMem); strcat(lpszSrc, szBuf); } if((file = fopen("test.jpg", "wb")) == NULL){ printf("ファイルオープンエラー\n"); goto end; } while(dwTotal){ fputc(*lpszSrc, file); lpszSrc++; dwTotal--; } fclose(file); end: GlobalUnlock(hMem); GlobalFree(hMem); InternetCloseHandle(hUrl); InternetCloseHandle(hInet); return 0; } <環境> Windows Vista VC++ 2005 EE

  • fscanfでループしてしまう。

    大変お世話になっております。 C言語についてお聞きしたいことがあります。 テキストファイルをデータとして読み込み、その数などを計算した結果をテキストファイルにしたいのです。簡略して次のような手順を歩みたいと思います。catalog.txtは数行からなり、各行の34文字目から38文字目までが実数で、これを抽出して各行の実数データを計算したいのですが、作成されたファイルは一行目の計算が無限にループしています。 以下がプログラムです。 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> main(){ FILE *fp, *fp2; char str[1024]; char buf[256]; double i, kekka; if((fp = fopen("catalog.txt", "r")) == NULL){ printf("file open error1\n"); exit(1); } if((fp2 = fopen("kekka.txt", "w")) == NULL){ printf("file open error2\n"); exit(1); } while( fscanf(fp, "%[^\n]", str) != EOF ){ strncpy(buf, &str[33], 5); buf[5] = '\0'; i = atof(buf); kekka = 2 * i; fprintf(fp2, "%lf\n" ,kekka); } } 毎度すいませんがこの解決方法をご教授ください。よろしくお願いします。

  • どうやってフローチャートを書きますか

    #include<stdio.h>   void main()   {   FILE*fp;   char buf[128];   char *rc;   char fname[20];   do{   printf("file name>>>");   scanf("%s",fname);   fp=fopen(fname,"r");   if=(fp==NULL) printf("File Open Err¥n");   }while(fp==NULL);   rc=fgets(buf,128,fp);   while(rc!=NULL){    printf("%s",buf);    rc=fgets(buf,123,fp);    }    fclose(fp);    }

  • 二次元的な(?)文字列から指定した箇所の数を取り出す方法を教えてください

    はじめまして。 C++を勉強している途中なのですが、興味本位でwin32apiに手を出してみたのですが、文字列について混乱中です。 http://www.geocities.jp/ky_webid/win32c/051.htmlの使用例を参考にして、テキストファイルtext.txtから文字を抽出し、MessageBoxで表示できるようになりました。 使用例というのは、↓です。 HANDLE hFile; // ファイルを開く。ReadFile()が目的なのでGENERIC_READ指定が必須 hFile = CreateFile( _T("test.dat"), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( hFile != INVALID_HANDLE_VALUE ) // 本当に開くことができたか { TCHAR buf[256]; DWORD readsize; // 使わないとしても、読み取ったサイズは受け取らなくてはならない // bufに読み込んで、結果をメッセージボックスに表示 ReadFile( hFile, buf, sizeof(buf), &readsize, NULL ); buf[readsize] = _T('\0'); // 末尾に'\0'が無いので付加 MessageBox( hWnd, buf, _T("結果"), MB_OK ); // 最後に忘れずにファイルハンドルを閉じる CloseHandle( hFile ); } テキストファイルtext.txtの中身は、↓のようになっています。 1 2 aui 2 4 sd 6 7 db 2 1 cx ですので、MessageBoxでも、↑のように表示されたのを確認しました。 bufの中に↑の数字と文字が代入されているということなのでしょうが、たとえば4を指定したり、dbを指定したりと、一つずつ抽出する方法がわかりません。 配列みたいにbuf[1][1]と書いてみても、「int型はcharに変換できない」といった感じのエラーが表示されるだけでした。 この文字列bufにある文字や数字を一つずつ抽出する方法を教えてください。

  • コンパイルエラーの原因がわからず困っています。

    こんばんは。 どなたか以下のプログラム(test4.c)が何故コンパイル出来ないのか教えて頂けませんか。行数は見やすいように一時的につけさせて頂きました。 1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<unistd.h> 5 #include<errno.h> 6 #include<signal.h> 7 #include<sys/types.h> 8 9 10 11 12 13 int main(){ 14 FILE *fp,*fp2; 15 char str[1024]; 16 char *tok; 17 char buf[256]; 18 fp = fopen("file.txt","r"); 19 int i = 0; 20 fp2 = fopen("out.txt","a"); 21 22 while((str = fgets(str,1024,fp)) == EOF){ 23 24 while(1){ 25 // 前文を取得 26 tok = strtok(str, "("); 27 printf("%s\n",tok); 28 strcat(buf, tok); 29 30 // 中文を取得 31 tok = strtok(NULL, ")"); 32 if(tok == NULL)break; 33 tok = strtok(NULL, ")"); 34 if(tok == NULL)break; 35 36 *(tok + 1) = '\0'; 37 tok = strtok(NULL, "CEUFRSAP.");//フラグをトークンの材料にする 38 strcat(buf,tok); 39 40 // 後文を取得 41 tok = strtok(NULL, "("); 42 tok = strtok(NULL, ")"); 43 strcat(buf,"tcp "); 44 strcat(buf,tok); 45 break; 46 } 47 printf("%s\n",buf); 48 printf("%d行目です/n",i++); 49 fputs(buf,fp2); 50 } 51 52 printf("合計%d行です\n",i); 53 fclose(fp); 54 fclose(fp2); 55 return 0; 56 } 以下がコンパイルエラーの全文です。 test4.c: In function ‘main’: test4.c:22: error: incompatible types in assignment どんな些細な意見でも結構です。アドバイスをして頂けないでしょうか。どうぞよろしくお願いします。

  • ファイルを読み込んで条件式を満たさない

    ファイルを読み込んで一部の文字列が来たら別のファイルの文字列を書き込んでもらうプログラムを作ろうとしたのですが、何故かifを使って条件分岐を試みたところ分岐してくれません。 どのようにしたら分岐しますか? 出来ればソースもお願いします。 ---ソースの内容--- #include <stdio.h> #include <string.h> void main(void){ FILE *fp,*fp2; char buf[100],buf2[100]; fp=fopen("yasa.txt","r+"); while( fgets( buf, 100, fp ) != NULL ){ if(strcmp(buf,"じゃがいも")==0){ fp2=fopen("kuda.txt","r+"); while( fgets( buf2, 100, fp2 ) != NULL ){ printf("%s",buf2); } fclose(fp2); } else{ printf("%s",buf); } } fclose(fp); } ---ソースここまで--- ---yasa.txtの内容--- きゃべつ にんじん じゃがいも だいこん セロリ ---yasa.txtここまで--- ---kuda.txtの内容--- もも オレンジ みかん ぶどう ---kuda.txtここまで---

  • ファイル

    c言語初心者です。 どなたか教えていただけませんか? これだとiが定義されないことになってしまいます。 #include<stdio.h> #include<stdlib.h> int main() { FILE *fp; fp=fopen("monai", "w"); if(fp==NULL){ fprintf(stderr,"ファイルのオープンに失敗しました。\n"); exit(0); } int i; for(i=1;i<=30;i++) { if(i<=9){ fprintf(fp," %d ",i); } else if(i%10==0) { fprintf(fp,"%d\n",i); } else { fprintf(fp,"%d ",i); } } fclose(fp); return 0; } ビルドもできません。