用idHttp組件 進行多線程 下載 無法分割數據 每次都是一個完整文件 |
答題得分者是:blue
|
kCaRhC
一般會員 發表:1 回覆:0 積分:0 註冊:2008-06-05 發送簡訊給我 |
用idHttp組件 進行 多線程 下載
根據線程數 對文件進行分割 采用 temhttp.Request.ContentRangeStart := tstart; temhttp.Request.ContentRangeEnd := tlast; 但是 結果收到的並不是 從 start 到last 而還是一個完成文件。。。 比如 文件是 150k 下載回來的文件 如果是 2個進程 就是 300k 3個就是。。。很迷糊 請問下是什麽原因 下面是完整代碼 [code delphi] unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, IdBaseComponent, IdAntiFreezeBase, IdAntiFreeze, IdThreadComponent, IdFTP; type TThread1 = class(TThread) private fCount, tstart, tlast: integer; tURL, tFile, temFileName: string; tResume: Boolean; tStream: TFileStream; protected procedure Execute; override; public constructor create1(aURL, aFile, fileName: string; bResume: Boolean; Count, start, last: integer); procedure DownLodeFile(); //下載文件 end; type TForm1 = class(TForm) IdAntiFreeze1: TIdAntiFreeze; IdHTTP1: TIdHTTP; Button1: TButton; ProgressBar1: TProgressBar; IdThreadComponent1: TIdThreadComponent; Label1: TLabel; Label2: TLabel; Button2: TButton; Button3: TButton; ListBox1: TListBox; Edit1: TEdit; Edit2: TEdit; Label3: TLabel; Label4: TLabel; Edit3: TEdit; procedure Button1Click(Sender: TObject); procedure IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: integer); procedure IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: integer); procedure Button2Click(Sender: TObject); procedure IdHTTP1Status(ASender: TObject; const AStatus: TIdStatus; const AStatusText: string); procedure Button3Click(Sender: TObject); private public nn, aFileSize, avg: integer; MyThread: array[1..10] of TThread; procedure GetThread(); procedure AddFile(); function GetURLFileName(aURL: string): string; function GetFileSize(aURL: string): integer; end; var Form1: TForm1; implementation var AbortTransfer: Boolean; aURL, aFile: string; tcount: integer; //檢查文件是否全部下載完畢 {$R *.dfm} //get FileName function TForm1.GetURLFileName(aURL: string): string; var i: integer; s: string; begin //返回下載地址的文件名 s := aURL; i := Pos('/', s); while i <> 0 do {//去掉"/"前面的內容剩下的就是文件名了} begin Delete(s, 1, i); i := Pos('/', s); end; Result := s; end; //get FileSize function TForm1.GetFileSize(aURL: string): integer; var FileSize: integer; begin IdHTTP1.Head(aURL); FileSize := IdHTTP1.Response.ContentLength; IdHTTP1.Disconnect; Result := FileSize; end; //執行下載 procedure TForm1.Button1Click(Sender: TObject); var j: integer; begin tcount := 0; //Showmessage('OK!主線程在執行,獲得文件名並顯示在Edit2中'); aURL := Edit1.Text; //下載地址 aFile := GetURLFileName(Edit1.Text); //得到文件名 Edit3.Text := aFile; Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('文件名 :' aFile); nn := StrToInt(Edit2.Text); //線程數 Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('線程數 :' IntToStr(nn)); j := 1; aFileSize := GetFileSize(aURL); Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('文件大小:' IntToStr(aFileSize)); avg := trunc(aFileSize / nn); Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('塊大小 :' IntToStr(avg)); begin try GetThread(); while j <= nn do begin MyThread[j].Resume; //喚醒線程 j := j 1; end; except Showmessage('創建線程失敗!'); Exit; end; end; end; //開始下載前,將ProgressBar1的最大值設置為需要接收的數據大小. procedure TForm1.IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: integer); begin AbortTransfer := False; ProgressBar1.Max := AWorkCountMax; ProgressBar1.Min := 0; ProgressBar1.Position := 0; end; //接收數據的時候,進度將在ProgressBar1顯示出來. procedure TForm1.IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: integer); begin if AbortTransfer then begin IdHTTP1.Disconnect; //中斷下載 end; ProgressBar1.Position := AWorkCount; //ProgressBar1.Position:=ProgressBar1.Position AWorkCount; //*******顯示速度極快 Application.ProcessMessages; //***********************************這樣使用不知道對不對 end; //中斷下載 procedure TForm1.Button2Click(Sender: TObject); begin AbortTransfer := True; IdHTTP1.Disconnect; end; //狀態顯示 procedure TForm1.IdHTTP1Status(ASender: TObject; const AStatus: TIdStatus; const AStatusText: string); begin ListBox1.ItemIndex := ListBox1.Items.Add(AStatusText); end; //退出程序 procedure TForm1.Button3Click(Sender: TObject); begin Application.Terminate; end; //循環産生線程 procedure TForm1.GetThread(); var i: integer; start: array[1..100] of integer; last: array[1..100] of integer; //改用了數組,也可不用 fileName: string; begin i := 1; while i <= nn do begin start[i] := avg * (i - 1); last[i] := avg * i - 1; //這裏原先是last:=avg*i; Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('開始字節數' IntToStr(start[i]) '結束字節數' IntToStr(last[i])); if i = nn then begin last[i] := avg * i aFileSize - avg * nn; //這裏原先是aFileSize end; fileName := aFile IntToStr(i); MyThread[i] := TThread1.create1(aURL, aFile, fileName, False, i, start[i], last[i]); i := i 1; end; end; procedure TForm1.AddFile(); //合並文件 var mStream1, mStream2: TMemoryStream; i: integer; begin i := 1; mStream1 := TMemoryStream.Create; mStream2 := TMemoryStream.Create; mStream1.loadfromfile(aFile '1'); while i < nn do begin mStream2.loadfromfile(aFile IntToStr(i 1)); mStream1.seek(mStream1.size, soFromBeginning); mStream1.copyfrom(mStream2, mStream2.size); mStream2.clear; i := i 1; end; mStream2.free; mStream1.SaveToFile(aFile); mStream1.free; //刪除臨時文件 i := 1; while i <= nn do begin deletefile(aFile IntToStr(i)); i := i 1; end; Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('下載成功'); end; //構造函數 constructor TThread1.create1(aURL, aFile, fileName: string; bResume: Boolean; Count, start, last: integer); begin inherited Create(True); FreeOnTerminate := True; tURL := aURL; tFile := aFile; fCount := Count; tResume := bResume; tstart := start; tlast := last; temFileName := fileName; end; //下載文件函數 procedure TThread1.DownLodeFile(); var temhttp: TIdHTTP; begin temhttp := TIdHTTP.Create(nil); temhttp.onWorkBegin := Form1.IdHTTP1WorkBegin; temhttp.onwork := Form1.IdHTTP1Work; temhttp.onStatus := Form1.IdHTTP1Status; Form1.IdAntiFreeze1.OnlyWhenIdle := False; //設置使程序有反應. if FileExists(temFileName) then //如果文件已經存在 tStream := TFileStream.Create(temFileName, fmOpenWrite) else tStream := TFileStream.Create(temFileName, fmCreate); if tResume then {//續傳方式} begin Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('不允許續傳'); Exit; end else {//覆蓋或新建方式} begin Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('允許續傳'); temhttp.Request.ContentRangeStart := tstart; temhttp.Request.ContentRangeEnd := tlast; end; temhttp.Request.Accept := '*/*'; //temhttp.Request.Referer := temhttp.Request.UserAgent := 'User-Agent: Mozilla/4.0 (compatib le; MSIE 5.00; Windows 98)'; temhttp.Request.Pragma := 'no-cache'; temhttp.Request.CacheControl := 'no-cache'; temhttp.Request.Connection := 'close'; try temhttp.Get(tURL, tStream); //開始下載 Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add(temFileName '開始下載'); finally //tStream.Free; freeandnil(tStream); temhttp.Disconnect; end; end; procedure TThread1.Execute; begin if Form1.Edit1.Text <> '' then //synchronize(DownLodeFile) DownLodeFile else Exit; inc(tcount); if tcount = Form1.nn then {//當tcount=nn時代表全部下載成功} begin //Showmessage('全部下載成功!'); Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('正在合並刪除臨時文件'); //Form1.AddFile; end; end; end. [/code] |
blue
中階會員 發表:170 回覆:136 積分:81 註冊:2002-04-15 發送簡訊給我 |
Hi,
因不知您是否已解, 小弟正在找續傳的寫法, 故參考了您這篇, 試了一下,改成 // temhttp.Request.ContentRangeStart := tstart; // temhttp.Request.ContentRangeEnd := tlast; temhttp.Request.Range := IntToStr(tstart) '-' IntToStr(tlast); 就可以分段下載了, 謝謝! ===================引 用 kCaRhC 文 章=================== 用idHttp組件 進行 多線程 下載 根據線程數 對文件進行分割 采用 temhttp.Request.ContentRangeStart := tstart; temhttp.Request.ContentRangeEnd := tlast; 但是 結果收到的並不是 從 start 到last 而還是一個完成文件。。。 比如 文件是 150k 下載回來的文件 如果是 2個進程 就是 300k 3個就是。。。很迷糊 請問下是什麽原因 下面是完整代碼 [code delphi] unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, IdBaseComponent, IdAntiFreezeBase, IdAntiFreeze, IdThreadComponent, IdFTP; type TThread1 = class(TThread) private fCount, tstart, tlast: integer; tURL, tFile, temFileName: string; tResume: Boolean; tStream: TFileStream; protected procedure Execute; override; public constructor create1(aURL, aFile, fileName: string; bResume: Boolean; Count, start, last: integer); procedure DownLodeFile(); //下載文件 end; type TForm1 = class(TForm) IdAntiFreeze1: TIdAntiFreeze; IdHTTP1: TIdHTTP; Button1: TButton; ProgressBar1: TProgressBar; IdThreadComponent1: TIdThreadComponent; Label1: TLabel; Label2: TLabel; Button2: TButton; Button3: TButton; ListBox1: TListBox; Edit1: TEdit; Edit2: TEdit; Label3: TLabel; Label4: TLabel; Edit3: TEdit; procedure Button1Click(Sender: TObject); procedure IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: integer); procedure IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: integer); procedure Button2Click(Sender: TObject); procedure IdHTTP1Status(ASender: TObject; const AStatus: TIdStatus; const AStatusText: string); procedure Button3Click(Sender: TObject); private public nn, aFileSize, avg: integer; MyThread: array[1..10] of TThread; procedure GetThread(); procedure AddFile(); function GetURLFileName(aURL: string): string; function GetFileSize(aURL: string): integer; end; var Form1: TForm1; implementation var AbortTransfer: Boolean; aURL, aFile: string; tcount: integer; //檢查文件是否全部下載完畢 {$R *.dfm} //get FileName function TForm1.GetURLFileName(aURL: string): string; var i: integer; s: string; begin //返回下載地址的文件名 s := aURL; i := Pos('/', s); while i <> 0 do {//去掉"/"前面的內容剩下的就是文件名了} begin Delete(s, 1, i); i := Pos('/', s); end; Result := s; end; //get FileSize function TForm1.GetFileSize(aURL: string): integer; var FileSize: integer; begin IdHTTP1.Head(aURL); FileSize := IdHTTP1.Response.ContentLength; IdHTTP1.Disconnect; Result := FileSize; end; //執行下載 procedure TForm1.Button1Click(Sender: TObject); var j: integer; begin tcount := 0; //Showmessage('OK!主線程在執行,獲得文件名並顯示在Edit2中'); aURL := Edit1.Text; //下載地址 aFile := GetURLFileName(Edit1.Text); //得到文件名 Edit3.Text := aFile; Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('文件名 :' aFile); nn := StrToInt(Edit2.Text); //線程數 Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('線程數 :' IntToStr(nn)); j := 1; aFileSize := GetFileSize(aURL); Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('文件大小:' IntToStr(aFileSize)); avg := trunc(aFileSize / nn); Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('塊大小 :' IntToStr(avg)); begin try GetThread(); while j <= nn do begin MyThread[j].Resume; //喚醒線程 j := j 1; end; except Showmessage('創建線程失敗!'); Exit; end; end; end; //開始下載前,將ProgressBar1的最大值設置為需要接收的數據大小. procedure TForm1.IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: integer); begin AbortTransfer := False; ProgressBar1.Max := AWorkCountMax; ProgressBar1.Min := 0; ProgressBar1.Position := 0; end; //接收數據的時候,進度將在ProgressBar1顯示出來. procedure TForm1.IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: integer); begin if AbortTransfer then begin IdHTTP1.Disconnect; //中斷下載 end; ProgressBar1.Position := AWorkCount; //ProgressBar1.Position:=ProgressBar1.Position AWorkCount; //*******顯示速度極快 Application.ProcessMessages; //***********************************這樣使用不知道對不對 end; //中斷下載 procedure TForm1.Button2Click(Sender: TObject); begin AbortTransfer := True; IdHTTP1.Disconnect; end; //狀態顯示 procedure TForm1.IdHTTP1Status(ASender: TObject; const AStatus: TIdStatus; const AStatusText: string); begin ListBox1.ItemIndex := ListBox1.Items.Add(AStatusText); end; //退出程序 procedure TForm1.Button3Click(Sender: TObject); begin Application.Terminate; end; //循環産生線程 procedure TForm1.GetThread(); var i: integer; start: array[1..100] of integer; last: array[1..100] of integer; //改用了數組,也可不用 fileName: string; begin i := 1; while i <= nn do begin start[i] := avg * (i - 1); last[i] := avg * i - 1; //這裏原先是last:=avg*i; Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('開始字節數' IntToStr(start[i]) '結束字節數' IntToStr(last[i])); if i = nn then begin last[i] := avg * i aFileSize - avg * nn; //這裏原先是aFileSize end; fileName := aFile IntToStr(i); MyThread[i] := TThread1.create1(aURL, aFile, fileName, False, i, start[i], last[i]); i := i 1; end; end; procedure TForm1.AddFile(); //合並文件 var mStream1, mStream2: TMemoryStream; i: integer; begin i := 1; mStream1 := TMemoryStream.Create; mStream2 := TMemoryStream.Create; mStream1.loadfromfile(aFile '1'); while i < nn do begin mStream2.loadfromfile(aFile IntToStr(i 1)); mStream1.seek(mStream1.size, soFromBeginning); mStream1.copyfrom(mStream2, mStream2.size); mStream2.clear; i := i 1; end; mStream2.free; mStream1.SaveToFile(aFile); mStream1.free; //刪除臨時文件 i := 1; while i <= nn do begin deletefile(aFile IntToStr(i)); i := i 1; end; Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('下載成功'); end; //構造函數 constructor TThread1.create1(aURL, aFile, fileName: string; bResume: Boolean; Count, start, last: integer); begin inherited Create(True); FreeOnTerminate := True; tURL := aURL; tFile := aFile; fCount := Count; tResume := bResume; tstart := start; tlast := last; temFileName := fileName; end; //下載文件函數 procedure TThread1.DownLodeFile(); var temhttp: TIdHTTP; begin temhttp := TIdHTTP.Create(nil); temhttp.onWorkBegin := Form1.IdHTTP1WorkBegin; temhttp.onwork := Form1.IdHTTP1Work; temhttp.onStatus := Form1.IdHTTP1Status; Form1.IdAntiFreeze1.OnlyWhenIdle := False; //設置使程序有反應. if FileExists(temFileName) then //如果文件已經存在 tStream := TFileStream.Create(temFileName, fmOpenWrite) else tStream := TFileStream.Create(temFileName, fmCreate); if tResume then {//續傳方式} begin Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('不允許續傳'); Exit; end else {//覆蓋或新建方式} begin Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('允許續傳'); temhttp.Request.ContentRangeStart := tstart; temhttp.Request.ContentRangeEnd := tlast; end; temhttp.Request.Accept := '*/*'; //temhttp.Request.Referer := temhttp.Request.UserAgent := 'User-Agent: Mozilla/4.0 (compatib le; MSIE 5.00; Windows 98)'; temhttp.Request.Pragma := 'no-cache'; temhttp.Request.CacheControl := 'no-cache'; temhttp.Request.Connection := 'close'; try temhttp.Get(tURL, tStream); //開始下載 Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add(temFileName '開始下載'); finally //tStream.Free; freeandnil(tStream); temhttp.Disconnect; end; end; procedure TThread1.Execute; begin if Form1.Edit1.Text <> '' then //synchronize(DownLodeFile) DownLodeFile else Exit; inc(tcount); if tcount = Form1.nn then {//當tcount=nn時代表全部下載成功} begin //Showmessage('全部下載成功!'); Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('正在合並刪除臨時文件'); //Form1.AddFile; end; end; end. [/code] |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |