(一). 概述
最近做了个C/S文件下载工具,支持多任务, 多线程和断点续传功能. 其中部分代码是从网上找来的, 自己改了
许多Thread Bug, 并增加多任务, 断点续传等功能.
由于公司具有代码所有权, 不能将源代码共享.自己对比较Asp.net感兴趣, 业余时间自己做了个简单的, 基于
Asp.net2.0的, 目前能够执行对一个文件的下载任务, 但已经实现了多线程, 断点续传功能. 根据需要您可以增加
多任务 功能, 分享一下, 互相学习! 互相借鉴!
时间仓促, 此程序还没有做很多参数方面的优化. 可以作参考用.
(二).运行效果
](http://img.e-com-net.com/image/product/b35474a2688a471d9d23b0d4c4fdc2c6.jpg)
(三). 代码
1. 核心 DownLoadState.cs 文件代码
1
///
<summary>
2
///
Author:[ChengKing(ZhengJian)]
3
///
Blog:Http://blog.csdn.net/ChengKing
4
///
注:从网上找了个优秀代码
5
///
扩展如下功能:
6
///
1.解决一些线程相关的Bug;
7
///
2.扩展用控制文件实现断点续传功能.
8
///
</summary>
9
namespace
DownLoadComponent
10
{
11
///
<summary>
12
///
多线程辅助类(AddbyChengKing)
13
///
</summary>
14
public
class
Task
15
{
16
string
_FromFileName;
17
string
_ToFileName;
18
int
_ThreadNum;
19
20
public
Task(
string
FromFileName,
string
ToFileName,
int
ThreadNum)
21
{
22
this
._FromFileName
=
FromFileName;
23
this
._ToFileName
=
ToFileName;
24
this
._ThreadNum
=
ThreadNum;
25
}
26
27
public
string
FromFileName
28
{
29
get
30
{
31
return
_FromFileName;
32
}
33
set
34
{
35
_FromFileName
=
value;
36
}
37
}
38
public
string
ToFileName
39
{
40
get
41
{
42
return
_ToFileName;
43
}
44
set
45
{
46
_ToFileName
=
value;
47
}
48
}
49
public
int
ThreadNum
50
{
51
get
52
{
53
return
_ThreadNum;
54
}
55
set
56
{
57
_ThreadNum
=
value;
58
}
59
}
60
}
61
62
///
<summary>
63
///
记录下载的字节位置
64
///
</summary>
65
public
class
DownLoadState
66
{
67
private
string
_FileName;
68
69
private
string
_AttachmentName;
70
private
int
_Position;
71
private
string
_RequestURL;
72
private
string
_ResponseURL;
73
private
int
_Length;
74
75
private
byte
[]_Data;
76
77
public
string
FileName
78
{
79
get
80
{
81
return
_FileName;
82
}
83
}
84
85
public
int
Position
86
{
87
get
88
{
89
return
_Position;
90
}
91
}
92
93
public
int
Length
94
{
95
get
96
{
97
return
_Length;
98
}
99
}
100
101
102
public
string
AttachmentName
103
{
104
get
105
{
106
return
_AttachmentName;
107
}
108
}
109
110
public
string
RequestURL
111
{
112
get
113
{
114
return
_RequestURL;
115
}
116
}
117
118
public
string
ResponseURL
119
{
120
get
121
{
122
return
_ResponseURL;
123
}
124
}
125
126
127
public
byte
[]Data
128
{
129
get
130
{
131
return
_Data;
132
}
133
}
134
135
internal
DownLoadState(
string
RequestURL,
string
ResponseURL,
string
FileName,
string
AttachmentName,
int
Position,
int
Length,
byte
[]Data)
136
{
137
this
._FileName
=
FileName;
138
this
._RequestURL
=
RequestURL;
139
this
._ResponseURL
=
ResponseURL;
140
this
._AttachmentName
=
AttachmentName;
141
this
._Position
=
Position;
142
this
._Data
=
Data;
143
this
._Length
=
Length;
144
}
145
146
internal
DownLoadState(
string
RequestURL,
string
ResponseURL,
string
FileName,
string
AttachmentName,
int
Position,
int
Length,ThreadCallbackHandlertch)
147
{
148
this
._RequestURL
=
RequestURL;
149
this
._ResponseURL
=
ResponseURL;
150
this
._FileName
=
FileName;
151
this
._AttachmentName
=
AttachmentName;
152
this
._Position
=
Position;
153
this
._Length
=
Length;
154
this
._ThreadCallback
=
tch;
155
}
156
157
internal
DownLoadState(
string
RequestURL,
string
ResponseURL,
string
FileName,
string
AttachmentName,
int
Position,
int
Length)
158
{
159
this
._RequestURL
=
RequestURL;
160
this
._ResponseURL
=
ResponseURL;
161
this
._FileName
=
FileName;
162
this
._AttachmentName
=
AttachmentName;
163
this
._Position
=
Position;
164
this
._Length
=
Length;
165
}
166
167
private
ThreadCallbackHandler_ThreadCallback;
168
169
//
170
internal
void
StartDownloadFileChunk()
171
{
172
if
(
this
._ThreadCallback
!=
null
)
173
{
174
this
._ThreadCallback(
this
._RequestURL,
this
._FileName,
this
._Position,
this
._Length);
175
}
176
}
177
178
}
179
180
//
委托代理线程的所执行的方法签名一致
181
public
delegate
void
ThreadCallbackHandler(
string
S,
string
s,
int
I,
int
i);
182
183
//
异常处理动作
184
public
enum
ExceptionActions
185
{
186
Throw,
187
CancelAll,
188
Ignore,
189
Retry
190
}
191
192
///
<summary>
193
///
包含Exception事件数据的类
194
///
</summary>
195
public
class
ExceptionEventArgs:System.EventArgs
196
{
197
private
System.Exception_Exception;
198
private
ExceptionActions_ExceptionAction;
199
200
private
DownLoadState_DownloadState;
201
202
public
DownLoadStateDownloadState
203
{
204
get
205
{
206
return
_DownloadState;
207
}
208
}
209
210
public
ExceptionException
211
{
212
get
213
{
214
return
_Exception;
215
}
216
}
217
218
public
ExceptionActionsExceptionAction
219
{
220
get
221
{
222
return
_ExceptionAction;
223
}
224
set
225
{
226
_ExceptionAction
=
value;
227
}
228
}
229
230
internal
ExceptionEventArgs(System.Exceptione,DownLoadStateDownloadState)
231
{
232
this
._Exception
=
e;
233
this
._DownloadState
=
DownloadState;
234
}
235
}
236
237
///
<summary>
238
///
包含DownLoad事件数据的类
239
///
</summary>
240
public
class
DownLoadEventArgs:System.EventArgs
241
{
242
private
DownLoadState_DownloadState;
243
244
public
DownLoadStateDownloadState
245
{
246
get
247
{
248
return
_DownloadState;
249
}
250
}
251
252
public
DownLoadEventArgs(DownLoadStateDownloadState)
253
{
254
this
._DownloadState
=
DownloadState;
255
}
256
257
}
258
259
///
<summary>
260
///
支持断点续传多线程下载的类
261
///
</summary>
262
public
class
HttpWebClient
263
{
264
private
static
object
_SyncLockObject
=
new
object
();
265
266
public
delegate
void
DataReceiveEventHandler(HttpWebClientSender,DownLoadEventArgse);
267
268
public
event
DataReceiveEventHandlerDataReceive;
//
接收字节数据事件
269
270
public
delegate
void
ExceptionEventHandler(HttpWebClientSender,ExceptionEventArgse);
271
272
public
event
ExceptionEventHandlerExceptionOccurrs;
//
发生异常事件
273
274
private
int
_FileLength;
//
下载文件的总大小
275
276
public
static
ArrayListthreads;
277
278
public
int
FileLength
279
{
280
get
281
{
282
return
_FileLength;
283
}
284
}
285
286
///
<summary>
287
///
分块下载文件
288
///
</summary>
289
///
<paramname="Address">
URL地址
</param>
290
///
<paramname="FileName">
保存到本地的路径文件名
</param>
291
///
<paramname="ChunksCount">
块数,线程数
</param>
292
public
void
DownloadFile(
string
Address,
string
FileName,
int
ChunksCount)
293
{
294
int
p
=
0
;
//
position
295
int
s
=
0
;
//
chunksize
296
string
a
=
null
;
297
HttpWebRequesthwrq;
298
HttpWebResponsehwrp
=
null
;
299
try
300
{
301
302
hwrq
=
(HttpWebRequest)WebRequest.Create(
this
.GetUri(Address));
303
//
hwrq.Timeout=20000000;
304
//
if(hwrq.HaveResponse==false)
305
//
return;
306
//
hwrq.ProtocolVersion=HttpVersion.Version10;
307
//
WebProxywp=WebProxy.GetDefaultProxy();
308
//
hwrq.Proxy=wp;
309
hwrq.Method
=
"
GET
"
;
310
try
311
{
312
hwrp
=
(HttpWebResponse)hwrq.GetResponse();
313
}
314
catch
(Exceptione)
315
{
316
throw
new
Exception(e.Message);
317
}
318
319
long
L
=
hwrp.ContentLength;
320
321
//
如果文件太小,就不用分多线程,用一个线程下载即可.(目前控制在800K)
322
//
if(L<800000)
323
//
{
324
//
ChunksCount=1;
325
//
}
326
327
hwrq.Credentials
=
this
.m_credentials;
328
329
L
=
((L
==
-
1
)
||
(L
>
0x7fffffff
))
?
((
long
)
0x7fffffff
):L;
//
Int32.MaxValue该常数的值为2,147,483,647;即十六进制的0x7FFFFFFF
330
331
int
l
=
(
int
)L;
332
333
this
._FileLength
=
l;
334
335
bool
b
=
(hwrp.Headers[
"
Accept-Ranges
"
]
!=
null
&
hwrp.Headers[
"
Accept-Ranges
"
]
==
"
bytes
"
);
336
a
=
hwrp.Headers[
"
Content-Disposition
"
];
//
attachment
337
if
(a
!=
null
)
338
{
339
a
=
a.Substring(a.LastIndexOf(
"
filename=
"
)
+
9
);
340
}
341
else
342
{
343
a
=
FileName;
344
}
345
346
int
ss
=
s;
347
if
(b)
348
{
349
if
(ExistControlFile(FileName))
//
是否存在文件
350
{
351
string
[]strBlocks
=
this
.ReadInfFromControlFile(FileName).Split(
new
char
[
2
]{
'
\r
'
,
'
\n
'
});
352
for
(
int
i
=
0
;i
<
strBlocks.Length;i
++
)
353
{
354
if
(strBlocks[i].Trim().Length
!=
0
&&
strBlocks[i].Substring(strBlocks[i].Length
-
1
)
==
"
0
"
)
355
{
356
string
[]strRe
分享到:
评论