Delphi完成的斷點續傳例子,在網絡應用中,斷點續傳是相當實用的,比如自動升級、或下載程序中,都可以用到。在Delphi7中,可以使用TIdHTTP和TIdFTP組件實現基於HTTP協議的斷點續傳和FTP協議的斷點續傳,都是使用的Indy系列組件,使用方法大同小異,下面來看運行效果圖:
Delphi實現斷點續傳,完整代碼如下:
001
unit
Unit1;
002
interface
003
uses
004
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
005
Dialogs, StdCtrls, ComCtrls, IdFTP, IDBaseComponent, IdComponent,
006
IdTCPConnection, IdTCPClIEnt, IdHTTP, IdHTTPHeaderInfo, ExtCtrls;
007
type
008
TForm1 =
class
(TForm)
009
ListBox1: TListBox;
010
Panel1: TPanel;
011
Label1: TLabel;
012
Label2: TLabel;
013
Button1: TButton;
014
ProgressBar1: TProgressBar;
015
Button2: TButton;
016
IdHTTP1: TIdHTTP;
017
IdFTP1: TIdFTP;
018
Button3: TButton;
019
ComboBox1: TComboBox;
020
procedure
Button2Click(Sender: TObject);
021
procedure
Button1Click(Sender: TObject);
022
procedure
IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode;
023
const
AWorkCount:
Integer
);
024
procedure
IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
025
const
AWorkCountMax:
Integer
);
026
procedure
IdHTTP1WorkEnd(Sender: TObject; AWorkMode: TWorkMode);
027
procedure
IdHTTP1Status(ASender: TObject;
const
AStatus: TIdStatus;
028
const
AStatusText:
string
);
029
procedure
Button3Click(Sender: TObject);
030
private
031
AbortTransfer:
Boolean
;
//是否中斷
032
BytesToTransfer:
LongWord
;
//下載總大小
033
procedure
FTPDownLoad(aURL, aFile:
string
; bResume:
Boolean
);
034
procedure
HttpDownLoad(aURL, aFile:
string
; bResume:
Boolean
);
035
procedure
MyDownLoad(aURL, aFile:
string
; bResume:
Boolean
);
036
function
GetProt(aURL:
string
):
Byte
;
037
function
GetURLFileName(aURL:
string
):
string
;
038
procedure
GetFTPParams(aURL:
string
;
var
sName, sPass, sHost, sPort,
039
sDir:
string
);
040
{ Private declarations }
041
public
042
{ Public declarations }
043
end
;
044
var
045
Form1: TForm1;
046
var
047
AverageSpeed:
Double
=
0
;
048
implementation
049
{$R *.dfm}
050
procedure
TForm1
.
Button2Click(Sender: TObject);
051
begin
052
AbortTransfer :=
True
;
053
end
;
054
function
TForm1
.
GetProt(aURL:
string
):
Byte
;
055
begin
//檢測下載的地址是http還是FTP
056
Result :=
0
;
057
if
Pos(
'http'
, LowerCase(aURL)) =
1
then
058
Result :=
1
;
//http協議
059
if
Pos(
'FTP'
, LowerCase(aURL)) =
1
then
060
Result :=
2
;
//FTP協議
061
end
;
062
function
TForm1
.
GetURLFileName(aURL:
string
):
string
;
063
var
064
i:
integer
;
065
s:
string
;
066
begin
//返回下載地址的文件名
067
s := aURL;
068
i := Pos(
'/'
, s);
069
while
i <>
0
do
//去掉"/"前面的內容剩下的就是文件名了
070
begin
071
Delete(s,
1
, i);
072
i := Pos(
'/'
, s);
073
end
;
074
Result := s;
075
end
;
076
procedure
TForm1
.
GetFTPParams(aURL:
string
;
var
sName, sPass, sHost, sPort, sDir:
string
);
077
var
078
i, j:
integer
;
079
s, tmp:
string
;
080
begin
//分析FTP地址的登陸用戶名,密碼和目錄
081
s := aURL;
082
if
Pos(
'FTP://'
, LowerCase(s)) <>
0
then
//去掉FTP頭
083
Delete(s,
1
,
6
);
084
i := Pos(
'@'
, s);
085
if
i <>
0
then
//地址含用戶名,也可能含密碼
086
begin
087
tmp := Copy(s,
1
, i -
1
);
088
s := copy(s, i+
1
, Length(s));
089
j := Pos(
':'
, tmp);
090
if
j <>
0
then
//包含密碼
091
begin
092
sName := Copy(tmp,
1
, j -
1
);
//得到用戶名
093
sPass := Copy(tmp, j +
1
, i - j -
1
);
//得到密碼
094
end
else
095
begin
096
sName := tmp;
097
sPass := Inputbox(
'輸入框'
,
'請輸入登陸FTP密碼'
,
''
);
098
end
;
099
end
else
//匿名用戶
100
begin
101
sName :=
'anonymous'
;
102
sPass :=
'[email protected]'
;
103
end
;
104
i := Pos(
':'
, s);
105
j := Pos(
'/'
, s);
106
sHost := Copy(s,
1
, j -
1
);
//主機
107
if
i <>
0
then
//含端口
108
sPort := Copy(s, i +
1
, j - i -
1
)
else
109
sPort :=
'21'
;
//默認21端口
110
tmp := Copy(s, j +
1
, Length(s));
111
while
j <>
0
do
112
begin
113
Delete(s,
1
, j);
114
j := Pos(
'/'
, s);
115
end
;
//目錄
116
sDir :=
'/'
+ Copy(tmp,
1
, Length(tmp) - Length(s) -
1
);
117
end
;
118
procedure
TForm1
.
FTPDownLoad(aURL, aFile:
string
; bResume:
Boolean
);
119
var
120
tStream: TFileStream;
121
sName, sPass, sHost, sPort, sDir:
string
;
122
begin
//FTP方式下載
123
if
FileExists(aFile)
then
//建立文件流
124
tStream := TFileStream
.
Create(aFile, fmOpenWrite)
else
125
tStream := TFileStream
.
Create(aFile, fmCreate);
126
GetFTPParams(aURL, sName, sPass, sHost, sPort, sDir);
127
with
IdFTP1
do
128
try
129
if
Connected
then
Disconnect;
//重新連接
130
Username := sName;
131
PassWord := sPass;
132
Host := sHost;
133
Port := StrToInt(sPort);
134
Connect;
135
except
136
exit;
137
end
;
138
IdFTP1
.
ChangeDir(sDir);
//改變目錄
139
BytesToTransfer := IdFTP1
.
Size(aFile);
140
try
141
if
bResume
then
//續傳
142
begin
143
tStream
.
Position := tStream
.
Size;
144
IdFTP1
.
Get(aFile, tStream,
True
);
145
end
else
146
begin
147
IdFTP1
.
Get(aFile, tStream,
False
);
148
end
;
149
finally
150
tStream
.
Free;
151
end
;
152
end
;
153
procedure
TForm1
.
HttpDownLoad(aURL, aFile:
string
; bResume:
Boolean
);
154
var
155
tStream: TFileStream;
156
begin
//Http方式下載
157
if
FileExists(aFile)
then
//如果文件已經存在
158
tStream := TFileStream
.
Create(aFile, fmOpenWrite)
else
159
tStream := TFileStream
.
Create(aFile, fmCreate);
160
if
bResume
then
//續傳方式
161
begin
162
IdHTTP1
.
Request
.
ContentRangeStart := tStream
.
Size -
1
;
163
tStream
.
Position := tStream
.
Size -
1
;
//移動到最後繼續下載
164
IdHTTP1
.
Head(aURL);
165
IdHTTP1
.
Request
.
ContentRangeEnd := IdHTTP1
.
Response
.
ContentLength;
166
end
else
//覆蓋或新建方式
167
begin
168
IdHTTP1
.
Request
.
ContentRangeStart :=
0
;
169
end
;
170
try
171
IdHTTP1
.
Get(aURL, tStream);
//開始下載
172
finally
173
tStream
.
Free;
174
end
;
175
end
;
176
procedure
TForm1
.
MyDownLoad(aURL, aFile:
string
; bResume:
Boolean
);
177
begin
178
case
GetProt(aURL)
of
179
0
: ShowMessage(
'不可識別的地址!'
);
180
1
: HttpDownLoad(aURL, aFile, bResume);
181
2
: FTPDownLoad(aURL, aFile, bResume);
182
end
;
183
end
;
184
procedure
TForm1
.
Button1Click(Sender: TObject);
185
var
186
aURL, aFile:
string
;
187
begin
188
aURL := ComboBox1
.
Text;
//下載地址,例如"http://www.baidu.com/update/test.exe"
189
aFile := GetURLFileName(aURL);
//得到文件名,例如"test.exe"
190
if
FileExists(aFile)
then
191
begin
192
case
MessageDlg(
'文件已經存在,是否續傳?'
, mtConfirmation, mbYesNoCancel,
0
)
of
193
mrYes: MyDownLoad(aURL, aFile,
True
);
//續傳
194
mrNo: MyDownLoad(aURL, aFile,
False
);
//覆蓋
195
mrCancel: Exit;
//取消
196
end
;
197
end
else
MyDownLoad(aURL, aFile,
False
);
//建立新文件下載
198
end
;
199
procedure
TForm1
.
IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode;
200
const
AWorkCount:
Integer
);
201
begin
202
if
AbortTransfer
then
203
begin
//中斷下載
204
IdHTTP1
.
Disconnect;
205
IdFTP1
.
Abort;
206
end
;
207
ProgressBar1
.
Position := AWorkCount;
208
Application
.
ProcessMessages;
209
end
;
210
procedure
TForm1
.
IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
211
const
AWorkCountMax:
Integer
);
212
begin
213
AbortTransfer :=
False
;
214
if
AWorkCountMax >
0
then
215
ProgressBar1
.
Max := AWorkCountMax
else
216
ProgressBar1
.
Max := BytesToTransfer;
217
end
;
218
procedure
TForm1
.
IdHTTP1WorkEnd(Sender: TObject; AWorkMode: TWorkMode);
219
begin
220
ProgressBar1
.
Position :=
0
;
221
end
;
222
procedure
TForm1
.
IdHTTP1Status(ASender: TObject;
const
AStatus: TIdStatus;
223
const
AStatusText:
string
);
224
begin
225
ListBox1
.
ItemIndex := ListBox1
.
Items
.
Add(AStatusText);
226
end
;
227
procedure
TForm1
.
Button3Click(Sender: TObject);
228
begin
229
Close;
230
end
;
231
end
.
程序所實現的主要功能由IdHTTP和IdFTP組件完成,你可借助本代碼學習Get過程實現斷點續傳的方法以及字符串的分析分解方法,初步掌握調試程序時斷點的使用,事件代碼的共用等。這裡我們同樣使用了流格式,不過這次不是內存流而是文件流。