全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:3617
推到 Plurk!
推到 Facebook!

用idHttp組件 進行多線程 下載 無法分割數據 每次都是一個完整文件

答題得分者是:blue
kCaRhC
一般會員


發表:1
回覆:0
積分:0
註冊:2008-06-05

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-06-05 12:47:05 IP:124.92.xxx.xxx 訂閱
用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
中階會員


發表:115
回覆:106
積分:59
註冊:2002-04-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2014-12-23 11:23:50 IP:122.146.xxx.xxx 訂閱
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]
系統時間:2017-12-15 18:00:23
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!