インターネットからファイルをDLするとき完了を待つには?

解決


武田  2005-06-30 00:08:25  No: 16062

皆様、いつもお世話になっております。
インターネットからIndex.htmlをダウンロードして保存するプログラムを作成しています。
ファイルのダウンロードが終わったら、リンクの解析などの処理したいのですが、どうやら完全にダウンロードが完了していないのに次の処理が開始するようで、エラーになるときがあります。
質問は、ダウンロード完了を待って次の処理をする方法を教えて頂きたいのです。
(小生はIEDownloadコンポーネントを使用しております)
コードの流れは
procedure TForm1.ToolButton2Click(Sender: TObject);
・・・・
{階層のディレクトリを再現してファイルを作成する}
IEDownload1.Go(URL, FilePath + FileName);)//ファイルを保存する
・・・
{ダウンロードが完了するまで待ちたい}
  while FileExists(FilePath + FileName) = False  do          
    Application.ProcessMessages
・・・
StringList.LoadFromFile(FilePath + FileName);(エラーの時があります)
・・・
{ダウンロードしたIndex.htmlを解析する関数などが続く}
・・・
よろしくご指導をお願い致します。m(__)m


シャチ  2005-06-30 00:16:03  No: 16063

IEDownloadのソースコードを見てみたところ、OnCompleteイベントがありますね。
これは試されましたか?


武田  2005-06-30 21:03:13  No: 16064

シャチ様、早速のご指摘をありがとうございます。
IEDownloadコンポーネントをダウンロードすると、DownloadDemo、LinkChecker、ResumeDemoの三つのデモプログラムが付いておりますので、そのなかのDownloadDemo、LinkCheckerのコンプリートで色々やってはいるのですが現在まだ私のレベルでは解決出来ておりません。
今まで(Result = S_OK)や 'Finished...'を捕らえて、やってはいるのですが、ここで言うS_OKやFinishedはOnDataのバッファーmemo2.lines.add(pchar(buffer));へのS_OKではないかと考えられます。
ところが説明によるとファイルへではなくて、その前の段階の保存で、このバッファーは複数のURLをロードすると順番はランダム、データーも混入すると書いてあるような気がします。だから分けたければ受けのMemoもその数だけ準備するような説明があります。(従ってそのままファイルへ落とせない。)
もっと勉強して、テストしながら本来の使い方を探ってみます。
仕方がないので今は、大きなタイムロスですがタイマーでファイルがダウンロード完了するまで待たせるようにしました。
それでも、先日Mr_XRAYさま他多数の先輩方のご指導により、スクラップ機能付きタブブラウザのひな形が完成しました。(超遅いですけど)
この場をお借りして、お礼を述べさせて頂きます。
もう少し、研究してみます。ありがとうございました。m(__)m
【DownloadDemoのOnコンプリート】
procedure TForm1.IEDownload1Complete(Sender: TBSCB; Stream: TStream;
  Result: HRESULT);
begin
  if (Result = S_OK) then
    memo1.lines.add('Download complete...')
  else
    memo1.lines.add(Errortext(Result) + ' ' + ResponseCodeText(Sender.ResponseCode));

【DownloadDemoのOndata】
procedure TForm1.IEDownload1Data(Sender: TBSCB; var Buffer: PByte;
  var BufLength: Cardinal);
begin
  memo2.lines.add(pchar(buffer));

【LinkCheckerのOnコンプリート】
procedure TForm1.IEDownload1Complete(Sender: TBSCB; Stream: TStream;
  Result: HRESULT);
begin
  if Sender.Responsecode = 200 then
    begin
    StringGrid1.Cells[1, Links.IndexOf(Sender.Url) + 1] := 'Finished...'

ResumeDemoの


尻切れ  2005-07-01 19:30:33  No: 16065

>StringList.LoadFromFile(FilePath + FileName);(エラーの時があります)
どんなエラーかな?
エラーが EFOpenErrorだったら、その原因はダウンロード完了とは無関係。
>ここで言うS_OKやFinishedはOnDataのバッファーmemo2.lines.add(pchar(buffer));へのS_OKではないかと…
そんなことはないけど…


武田  2005-07-03 08:56:40  No: 16066

尻切れ様、失礼しました。本日ここを覗いて、新しいレスがあることに気づきました。遅くなってm(__)m。
エラーは、
IEDownload1.Go(URL, FilePath + FileName);)
でダウンロードしますが実際は、/を¥に変換してサイトの階層をディレクトリの階層に変換して保存しています。そのためディレクトリの生成の時間もかかるかもしれません。
つぎに保存したindex.htmlファイルを分析してリンクリストを作成するため
StringListにロードしています。
StringList.LoadFromFile(FilePath + FileName);
ここで、「このファイルを開けない」とエラーが出ます。
階層などそのままで繰り返すと、エラーにならない場合があります。つまりロードするのに間に合ったのでしょうか。
やっと、解決策を私なりに見つけたのですが、
procedure TForm1.IEDownload1Complete(・・);
  if (Result = S_OK) then
    URL:= Sender.Url;
でURLを受け取り、
procedure TForm1.IEDownload1Data(・・);
  StringList.Add(pchar(buffer));URLが同じであることを確認して
bufferから直に受け取り、ファイルのダウンロードとは別にしたところ、
いまのところ、うまくいっています。
正しい使い方かどうかは解りませんが。
ありがとうございました。


解放せざるものアクセスすべからず  2005-07-05 00:13:58  No: 16067

IEDownload1.Go('サイトのURL', 'ファイル名');
でHTMLファイルをダウンロードした場合、IEDownload1Completeが呼び出された時点では、そのファイル(TFileStream)はまだ解放(Free)されていません。
解放されていないファイルに対してStringList.LoadfromFile()を実行するから、「ファイルを開けない」というEFOpenErrorエラーになるんですよ。

>procedure TForm1.IEDownload1Data(・・);
>begin
>  StringList.Add(pchar(buffer));
これはマズイですね。
bufferに取得されたデータは行単位になってはいませんよ。データは文字列の途中で切れている場合もあるんです。それをStringListにAddしたら文字列の途中に改行コードが挿入されてしまいます。取得したHTMLを分析する際には改行を無視しましょう。


武田  2005-07-08 00:32:10  No: 16068

[解放せざるものアクセスすべからず ]さん、ご指導を感謝します。
まだIEDownloadの使い方が解らず試行錯誤しております。
少し長くなりますが、次のように改良?しました。
実際にはDirなど作成する処理がありますが。
HTMLファイルのDLと解析用のStringListは分けて考える様にした。
procedure TForm1.ToolButton2Click();
    IEDownload1.Go(URL + 'index.htm');
    IEDownload1.Go(URL + 'index.html');
    IEDownload1.Go(URL + 'index.cgi');
    while  indexURL='' do
       Application.ProcessMessages;
    IEDownload1.Go(IndexURL, Dir + FileName);
・・・
S_OKが発生したらURLを取得する。
procedure TForm1.IEDownload1Complete();
  indexURL:= '';
  if (Result = S_OK) then indexURL:= Sender.Url;
・・・
バッファーをストリングリストにストックする。
procedure TForm1.IEDownload1Data();
  StringList.Add(pchar(buffer));
・・・
CRLFをカットする関数を作成して処理する。
procedure TForm1.CRLFCut(var StringList);
・・・
StringListのHTMLを解析する関数でHTML内のリンクを形成する。
解析した画像などのリンクでダウンロードする。

以上でWeBoxのように、サイトの階層を再現して画像ファイル等をDL出来るようになりましたが、
(#正直なところ、IEDownload1Complete()の使い方など理解しておりません。)
Index.htmlを開いても、画像が表示されないので、悪戦苦闘しています。


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

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






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