关于一个多线程分割下载文件的问题,请帮我看看,谢谢! 200分(100)

  • 主题发起人 主题发起人 lvxy
  • 开始时间 开始时间
L

lvxy

Unregistered / Unconfirmed
GUEST, unregistred user!
用idHttp组件进行多线程下载 根据线程数对文件进行分割 采用 temhttp.Request.ContentRangeStart := tstart; temhttp.Request.ContentRangeEnd := tlast; 但是结果收到的并不是从start到last而还是一个完成文件。 。 。 比如文件是150k 如果用5个线程下载,一个应该是30k才对,问题是现在是5个线程创建的文件都是150k这样别说加快速度下载了,等于慢了5倍..请问下是什么原因下面是完整代码unit Unit1;interfaceuses 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); procedure FormCreate(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;implementationvar AbortTransfer: Boolean; aURL, aFile: string; tcount: integer; //檢查文件是否全部下載完畢{$R *.dfm} //get FileNamefunction 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 FileSizefunction 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); //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.FormCreate(Sender: TObject);beginend; //循環産生線程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 := avg * (i - 1); last := avg * i - 1; //這裏原先是last:=avg*i; Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add( '開始字節數' + IntToStr(start) + '結束字節數' + IntToStr(last)); if i = nn then begin last := avg * i + aFileSize - avg * nn; //這裏原先是aFileSize end; fileName := aFile + IntToStr(i); MyThread := TThread1.create1(aURL, aFile, fileName, False, i, start, last); 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.IdHTTP1.OnWorkBegin; temhttp.onwork := Form1.IdHTTP1.OnWork; temhttp.onStatus := Form1.IdHTTP1.OnStatus; 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 Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add(temFileName + '開始下載'); temhttp.Get(tURL, tStream); //開始下載 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.
 
1.向用 Head 方法,然后读取IdHTTP1.Request.ContentLength 就可以获得要下载的文件的大小2.根据线程数去分割文件大小IdHTTP1.Request.CustomHeaders.Add('Range: bytes='+IntToStr(文件位置)+'-'#13#10);//从指定的位置下载数据3.把下载完的文件各部分重新组合起来。
 
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'这里面没有显示文件分割的段
 
后退
顶部