/* .Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类 (C# DIY HttpWebClient)
* Reflector 了一下 System.Net.WebClient ,改写或增加了若干:
* DownLoad、Upload 相关方法!
* DownLoad 相关改动较大!
* 增加了 DataReceive、ExceptionOccurrs 事件!
* 了解服务器端与客户端交互的 HTTP 协议参阅:
* 使文件下载的自定义连接支持 FlashGet 的断点续传多线程链接下载! JSP/Servlet 实现!
* http://blog.csdn.net/playyuer/archive/2004/08/02/58430.aspx
* 使文件下载的自定义连接支持 FlashGet 的断点续传多线程链接下载! C#/ASP.Net 实现!
* http://blog.csdn.net/playyuer/archive/2004/08/02/58281.aspx
*/
//2005-03-14 修订:
/* .Net/C#: 实现支持断点续传多线程下载的工具类
* Reflector 了一下 System.Net.WebClient ,改写或增加了若干:
* DownLoad、Upload 相关方法!
* 增加了 DataReceive、ExceptionOccurrs 事件
*/
namespace
Microshaoft
.
Utils
{
using
System
;
using
System
.IO
;
using
System
.Net
;
using
System
.
Text
;
using
System
.Security
;
using
System
.Threading
;
using
System
.Collections.Specialized
;
/// <summary>
/// 记录下载的字节位置
/// </summary>
public class
DownLoadState
{
private string
_FileName;
private string
_AttachmentName;
private int
_Position;
private string
_RequestURL;
private string
_ResponseURL;
private int
_Length;
private byte
[]
_Data;
public string
FileName
{
get
{
return
_FileName;
}
}
public int
Position
{
get
{
return
_Position;
}
}
public int
Length
{
get
{
return
_Length;
}
}
public string
AttachmentName
{
get
{
return
_AttachmentName;
}
}
public string
RequestURL
{
get
{
return
_RequestURL;
}
}
public string
ResponseURL
{
get
{
return
_ResponseURL;
}
}
public byte
[]
Data
{
get
{
return
_Data;
}
}
internal
DownLoadState
(
string
RequestURL,
string
ResponseURL,
string
FileName
,
string
AttachmentName,
int
Position
,
int
Length
,
byte
[]
Data
)
{
this
.
_FileName
=
FileName
;
this
.
_RequestURL
=
RequestURL;
this
.
_ResponseURL
=
ResponseURL;
this
.
_AttachmentName
=
AttachmentName;
this
.
_Position
=
Position
;
this
.
_Data
=
Data
;
this
.
_Length
=
Length
;
}
internal
DownLoadState
(
string
RequestURL,
string
ResponseURL,
string
FileName
,
string
AttachmentName,
int
Position
,
int
Length
, ThreadCallbackHandler tch
)
{
this
.
_RequestURL
=
RequestURL;
this
.
_ResponseURL
=
ResponseURL;
this
.
_FileName
=
FileName
;
this
.
_AttachmentName
=
AttachmentName;
this
.
_Position
=
Position
;
this
.
_Length
=
Length
;
this
.
_ThreadCallback
=
tch;
}
internal
DownLoadState
(
string
RequestURL,
string
ResponseURL,
string
FileName
,
string
AttachmentName,
int
Position
,
int
Length
)
{
this
.
_RequestURL
=
RequestURL;
this
.
_ResponseURL
=
ResponseURL;
this
.
_FileName
=
FileName
;
this
.
_AttachmentName
=
AttachmentName;
this
.
_Position
=
Position
;
this
.
_Length
=
Length
;
}
private
ThreadCallbackHandler _ThreadCallback;
public
HttpWebClient httpWebClient
{
get
{
return this
.
_hwc;
}
set
{
this
.
_hwc
= value
;
}
}
internal
Thread
thread
{
get
{
return
_thread;
}
set
{
_thread
= value
;
}
}
private
HttpWebClient _hwc;
private
Thread
_thread;
//
internal void
StartDownloadFileChunk
()
{
if
(
this
.
_ThreadCallback
!= null)
{
this
.
_ThreadCallback
(
this
.
_RequestURL,
this
.
_FileName,
this
.
_Position,
this
.
_Length
)
;
this
.
_hwc
.
OnThreadProcess
(
this
.
_thread
)
;
}
}
}
//委托代理线程的所执行的方法签名一致
public delegate void
ThreadCallbackHandler
(
string
S
,
string
s,
int
I
,
int
i
)
;
//异常处理动作
public enum
ExceptionActions
{
Throw
,
CancelAll,
Ignore
,
Retry
}
/// <summary>
/// 包含 Exception 事件数据的类
/// </summary>
public class
ExceptionEventArgs
:
System
.
EventArgs
{
private
System
.
Exception
_Exception
;
private
ExceptionActions _ExceptionAction;
private
DownLoadState _DownloadState;
public
DownLoadState DownloadState
{
get
{
return
_DownloadState;
}
}
public
Exception Exception
{
get
{
return
_Exception
;
}
}
public
ExceptionActions ExceptionAction
{
get
{
return
_ExceptionAction;
}
set
{
_ExceptionAction
= value
;
}
}
internal
ExceptionEventArgs
(
System
.
Exception
e, DownLoadState DownloadState
)
{
this
._Exception =
e;
this
.
_DownloadState
=
DownloadState;
}
}
/// <summary>
/// 包含 DownLoad 事件数据的类
/// </summary>
public class
DownLoadEventArgs
:
System
.
EventArgs
{
private
DownLoadState _DownloadState;
public
DownLoadState DownloadState
{
get
{
return
_DownloadState;
}
}
public
DownLoadEventArgs
(
DownLoadState DownloadState
)
{
this
.
_DownloadState
=
DownloadState;
}
}
public class
ThreadProcessEventArgs
:
System
.
EventArgs
{
private
Thread
_thread;
public
Thread
thread
{
get
{
return this
.
_thread;
}
}
public
ThreadProcessEventArgs
(
Thread
thread
)
{
this
.
_thread
=
thread;
}
}
/// <summary>
/// 支持断点续传多线程下载的类
/// </summary>
public class
HttpWebClient
{
private static object
_SyncLockObject
= new
object
()
;
public delegate void
DataReceiveEventHandler
(
HttpWebClient
Sender
, DownLoadEventArgs e
)
;
public event
DataReceiveEventHandler DataReceive;
//接收字节数据事件
public delegate void
ExceptionEventHandler
(
HttpWebClient
Sender
, ExceptionEventArgs e
)
;
public event
ExceptionEventHandler ExceptionOccurrs;
//发生异常事件
public delegate void
ThreadProcessEventHandler
(
HttpWebClient
Sender
, ThreadProcessEventArgs e
)
;
public event
ThreadProcessEventHandler ThreadProcessEnd;
//发生多线程处理完毕事件
private int
_FileLength;
//下载文件的总大小
public int
FileLength
{
get
{
return
_FileLength;
}
}
/// <summary>
/// 分块下载文件
/// </summary>
/// <param name="Address">URL 地址</param>
/// <param name="FileName">保存到本地的路径文件名</param>
/// <param name="ChunksCount">块数,线程数</param>
public void
DownloadFile
(
string
Address
,
string
FileName
,
int
ChunksCount
)
{
int
p
=
0;
// position
int
s
=
0;
// chunk size
string
a
= null
;
HttpWebRequest
hwrq;
HttpWebResponse
hwrp
= null
;
try
{
hwrq
= (
HttpWebRequest
)
WebRequest
.
Create
(
this
.
GetUri
(
Address
))
;
hwrp
= (
HttpWebResponse
)
hwrq
.
GetResponse
()
;
long
L =
hwrp
.
ContentLength
;
hwrq
.
Credentials
=
this
.
m_credentials;
L = ((L == -
1
) || (L >
0x7fffffff
)) ? ((
long
)
0x7fffffff
) : L
;
//Int32.MaxValue 该常数的值为 2,147,483,647; 即十六进制的 0x7FFFFFFF
int
l
= (
int
) L
;
this
.
_FileLength
=
l;
// 在本地预定空间(竟然在多线程下不用先预定空间)
// FileStream sw = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
// sw.Write(new byte[l], 0, l);
// sw.Close();
// sw = null;
bool
b
= (
hwrp
.
Headers
[
"Accept-Ranges"
] != null &
hwrp
.
Headers
[
"Accept-Ranges"
] ==
"bytes"
)
;
a
=
hwrp
.
Headers
[
"Content-Disposition"
]
;
//attachment
if
(
a
!= null)
{
a
=
a
.
Substring
(
a
.
LastIndexOf
(
"filename="
) +
9
)
;
}
else
{
a
=
FileName
;
}
int
ss
=
s;
if
(
b
)
{
s
=
l
/
ChunksCount;
if
(
s
<
2
*
64
*
1024
)
//块大小至少为 128 K 字节
{
s
=
2
*
64
*
1024;
}
ss
=
s;
int
i
=
0;
while
(
l
>
s
)
{
l
-=
s;
if
(
l
<
s
)
{
s
+=
l;
}
if
(
i
++ >
0
)
{
DownLoadState x
= new
DownLoadState
(
Address
, hwrp
.
ResponseUri
.
AbsolutePath
,
FileName
, a, p, s,
new
ThreadCallbackHandler
(
this
.
DownloadFileChunk
))
;
// 单线程下载
// x.StartDownloadFileChunk();
x
.
httpWebClient
=
this
;
//多线程下载
Thread
t
= new
Thread
(new
ThreadStart
(
x
.
StartDownloadFileChunk
))
;
//this.OnThreadProcess(t);
t
.
Start
()
;
}
p
+=
s;
}
s
=
ss;
byte
[]
buffer
=
this
.
ResponseAsBytes
(
Address
, hwrp, s,
FileName
)
;
this
.
OnThreadProcess
(
Thread
.
CurrentThread
)
;
// lock (_SyncLockObject)
// {
// this._Bytes += buffer.Length;
// }
}
}
catch
(
Exception
e
)
{
ExceptionActions ea
=
ExceptionActions
.Throw
;
if
(
this
.
ExceptionOccurrs
!= null)
{
DownLoadState x
= new
DownLoadState
(
Address
, hwrp
.
ResponseUri
.
AbsolutePath
,
FileName
, a, p, s
)
;
ExceptionEventArgs eea
= new
ExceptionEventArgs
(
e, x
)
;
ExceptionOccurrs
(
this
, eea
)
;
ea
=
eea
.
ExceptionAction;
}
if
(
ea
==
ExceptionActions
.Throw)
{
if
(!(
e
is
WebException
) && !(
e
is
SecurityException
))
{
throw
new
WebException
(
"net_webclient"
, e
)
;
}
throw
;
}
}
}
internal void
OnThreadProcess
(
Thread
t
)
{
if
(
ThreadProcessEnd
!= null)
{
ThreadProcessEventArgs tpea
= new
ThreadProcessEventArgs
(
t
)
;
ThreadProcessEnd
(
this
, tpea
)
;
}
}
/// <summary>
/// 下载一个文件块,利用该方法可自行实现多线程断点续传
/// </summary>
/// <param name="Address">URL 地址</param>
/// <param name="FileName">保存到本地的路径文件名</param>
/// <param name="Length">块大小</param>
public void
DownloadFileChunk
(
string
Address
,
string
FileName
,
int
FromPosition,
int
Length
)
{
HttpWebResponse
hwrp
= null
;
string
a
= null
;
try
{
//this._FileName = FileName;
HttpWebRequest
hwrq
= (
HttpWebRequest
)
WebRequest
.
Create
(
this
.
GetUri
(
Address
))
;
//hwrq.Credentials = this.m_credentials;
hwrq
.
AddRange
(
FromPosition
)
;
hwrp
= (
HttpWebResponse
)
hwrq
.
GetResponse
()
;
a
=
hwrp
.
Headers
[
"Content-Disposition"
]
;
//attachment
if
(
a
!= null)
{
a
=
a
.
Substring
(
a
.
LastIndexOf
(
"filename="
) +
9
)
;
}
else
{
a
=
FileName
;
}
byte
[]
buffer
=
this
.
ResponseAsBytes
(
Address
, hwrp,
Length
,
FileName
)
;
// lock (_SyncLockObject)
// {
// this._Bytes += buffer.Length;
// }
}
catch
(
Exception
e
)
{
ExceptionActions ea
=
ExceptionActions
.Throw
;
if
(
this
.
ExceptionOccurrs
!= null)
{
DownLoadState x
= new
DownLoadState
(
Address
, hwrp
.
ResponseUri
.
AbsolutePath
,
FileName
, a, FromPosition,
Length
)
;
ExceptionEventArgs eea
= new
ExceptionEventArgs
(
e, x
)
;
ExceptionOccurrs
(
this
, eea
)
;
ea
=
eea
.
ExceptionAction;
}
if
(
ea
==
ExceptionActions
.Throw)
{
if
(!(
e
is
WebException
) && !(
e
is
SecurityException
))
{
throw
new
WebException
(
"net_webclient"
, e
)
;
}
throw
;
}
}
}
internal byte
[]
ResponseAsBytes
(
string
RequestURL,
WebResponse
Response
,
long
Length
,
string
FileName
)
{
string
a
= null
;
//AttachmentName
int
P =
0;
//整个文件的位置指针
int
num2
=
0;
try
{
a
=
Response
.
Headers
[
"Content-Disposition"
]
;
//attachment
if
(
a
!= null)
{
a
=
a
.
Substring
(
a
.
LastIndexOf
(
"filename="
) +
9
)
;
}
long
num1
=
Length
;
//Response.ContentLength;
bool
flag1
=
false
;
if
(
num1
== -
1
)
{
flag1
=
true
;
num1
=
0x10000;
//64k
}
byte
[]
buffer1
= new
byte
[(
int
)
num1
]
;
int
p
=
0;
//本块的位置指针
string
s
=
Response
.
Headers
[
"Content-Range"
]
;
if
(
s
!= null)
{
s
=
s
.
Replace
(
"bytes "
,
""
)
;
s
=
s
.
Substring
(
0, s
.
IndexOf
(
"-"
))
;
P =
Convert
.
ToInt32
(
s
)
;
}
int
num3
=
0;
Stream
S =
Response
.
GetResponseStream
()
;
do
{
num2
= S.
Read
(
buffer1, num3,
((
int
)
num1
) -
num3
)
;
num3
+=
num2;
if
(
flag1
&& (
num3
==
num1
))
{
num1
+=
0x10000;
byte
[]
buffer2
= new
byte
[(
int
)
num1
]
;
Buffer
.
BlockCopy
(
buffer1, 0, buffer2, 0, num3
)
;
buffer1
=
buffer2;
}
// lock (_SyncLockObject)
// {
// this._bytes += num2;
// }
if
(
num2
>
0
)
{
if
(
this
.
DataReceive
!= null)
{
byte
[]
buffer
= new
byte
[
num2
]
;
Buffer
.
BlockCopy
(
buffer1, p, buffer, 0, buffer
.
Length
)
;
DownLoadState dls
= new
DownLoadState
(
RequestURL,
Response
.
ResponseUri
.
AbsolutePath
,
FileName
, a,
P
, num2, buffer
)
;
DownLoadEventArgs dlea
= new
DownLoadEventArgs
(
dls
)
;
//触发事件
this
.
OnDataReceive
(
dlea
)
;
//System.Threading.Thread.Sleep(100);
}
p
+=
num2;
//本块的位置指针
P +=
num2;
//整个文件的位置指针
}
else
{
break
;
}
}
while
(
num2
!=
0
)
;
S.
Close
()
;
S = null
;
if
(
flag1
)
{
byte
[]
buffer3
= new
byte
[
num3
]
;
Buffer
.
BlockCopy
(
buffer1, 0, buffer3, 0, num3
)
;
buffer1
=
buffer3;
}
return
buffer1;
}
catch
(
Exception
e
)
{
ExceptionActions ea
=
ExceptionActions
.Throw
;
if
(
this
.
ExceptionOccurrs
!= null)
{
DownLoadState x
= new
DownLoadState
(
RequestURL,
Response
.
ResponseUri
.
AbsolutePath
,
FileName
, a,
P
, num2
)
;
ExceptionEventArgs eea
= new
ExceptionEventArgs
(
e, x
)
;
ExceptionOccurrs
(
this
, eea
)
;
ea
=
eea
.
ExceptionAction;
}
if
(
ea
==
ExceptionActions
.Throw)
{
if
(!(
e
is
WebException
) && !(
e
is
SecurityException
))
{
throw
new
WebException
(
"net_webclient"
, e
)
;
}
throw
;
}
return
null
;
}
}
private void
OnDataReceive
(
DownLoadEventArgs e
)
{
//触发数据到达事件
DataReceive
(
this
, e
)
;
}
public byte
[]
UploadFile
(
string
address,
string
fileName
)
{
return this
.
UploadFile
(
address,
"POST"
, fileName,
"file"
)
;
}
public string
UploadFileEx
(
string
address,
string
method,
string
fileName,
string
fieldName
)
{
return
Encoding
.
ASCII
.
GetString
(
UploadFile
(
address, method, fileName, fieldName
))
;
}
public byte
[]
UploadFile
(
string
address,
string
method,
string
fileName,
string
fieldName
)
{
byte
[]
buffer4;
FileStream
stream1
= null
;
try
{
fileName
=
Path
.
GetFullPath
(
fileName
)
;
string
text1
=
"---------------------"
+
DateTime
.
Now
.
Ticks
.
ToString
(
"x"
)
;
string
text2
=
"application/octet-stream"
;
stream1
= new
FileStream
(
fileName,
FileMode.
Open
,
FileAccess.
Read
)
;
WebRequest
request1
=
WebRequest
.
Create
(
this
.
GetUri
(
address
))
;
request1
.
Credentials
=
this
.
m_credentials;
request1
.
ContentType
=
"multipart/form-data; boundary="
+
text1;
request1
.
Method
=
method;
string
[]
textArray1
= new
string
[
7
] {
"--"
, text1,
"\r\nContent-Disposition: form-data; name=\""
+
fieldName
+
"\"; filename=\""
,
Path
.
GetFileName
(
fileName
)
,
"\"\r\nContent-Type: "
, text2,
"\r\n\r\n"
}
;
string
text3
=
string
.
Concat
(
textArray1
)
;
byte
[]
buffer1
=
Encoding
.
UTF8
.
GetBytes
(
text3
)
;
byte
[]
buffer2
=
Encoding
.
ASCII
.
GetBytes
(
"\r\n--"
+
text1
+
"\r\n"
)
;
long
num1
=
0x7fffffffffffffff;
try
{
num1
=
stream1
.
Length
;
request1
.
ContentLength
= (
num1
+
buffer1
.
Length
) +
buffer2
.
Length
;
}
catch
{
}
byte
[]
buffer3
= new
byte
[
Math
.
Min
(
0x2000,
(
int
)
num1
)]
;
using
(
Stream
stream2
=
request1
.
GetRequestStream
())
{
int
num2;
stream2
.
Write
(
buffer1, 0, buffer1
.
Length
)
;
do
{
num2
=
stream1
.
Read
(
buffer3, 0, buffer3
.
Length
)
;
if
(
num2
!=
0
)
{
stream2
.
Write
(
buffer3, 0, num2
)
;
}
}
while
(
num2
!=
0
)
;
stream2
.
Write
(
buffer2, 0, buffer2
.
Length
)
;
}
stream1
.
Close
()
;
stream1
= null
;
WebResponse
response1
=
request1
.
GetResponse
()
;
buffer4
=
this
.
ResponseAsBytes
(
response1
)
;
}
catch
(
Exception
exception1
)
{
if
(
stream1
!= null)
{
stream1
.
Close
()
;
stream1
= null
;
}
if
(!(
exception1
is
WebException
) && !(
exception1
is
SecurityException
))
{
//throw new WebException(SR.GetString("net_webclient"), exception1);
throw
new
WebException
(
"net_webclient"
, exception1
)
;
}
throw
;
}
return
buffer4;
}
private byte
[]
ResponseAsBytes
(
WebResponse
response
)
{
int
num2;
long
num1
=
response
.
ContentLength
;
bool
flag1
=
false
;
if
(
num1
== -
1
)
{
flag1
=
true
;
num1
=
0x10000;
}
byte
[]
buffer1
= new
byte
[(
int
)
num1
]
;
Stream
stream1
=
response
.
GetResponseStream
()
;
int
num3
=
0;
do
{
num2
=
stream1
.
Read
(
buffer1, num3,
((
int
)
num1
) -
num3
)
;
num3
+=
num2;
if
(
flag1
&& (
num3
==
num1
))
{
num1
+=
0x10000;
byte
[]
buffer2
= new
byte
[(
int
)
num1
]
;
Buffer
.
BlockCopy
(
buffer1, 0, buffer2, 0, num3
)
;
buffer1
=
buffer2;
}
}
while
(
num2
!=
0
)
;
stream1
.
Close
()
;
if
(
flag1
)
{
byte
[]
buffer3
= new
byte
[
num3
]
;
Buffer
.
BlockCopy
(
buffer1, 0, buffer3, 0, num3
)
;
buffer1
=
buffer3;
}
return
buffer1;
}
private
NameValueCollection
m_requestParameters;
private
Uri
m_baseAddress;
private
ICredentials
m_credentials
=
CredentialCache
.
DefaultCredentials
;
public
ICredentials
Credentials
{
get
{
return this
.
m_credentials;
}
set
{
this
.
m_credentials
= value
;
}
}
public
NameValueCollection
QueryString
{
get
{
if
(
this
.
m_requestParameters
== null)
{
this
.
m_requestParameters
= new
NameValueCollection
()
;
}
return this
.
m_requestParameters;
}
set
{
this
.
m_requestParameters
= value
;
}
}
public string
BaseAddress
{
get
{
if
(
this
.
m_baseAddress
!= null)
{
return this
.
m_baseAddress
.
ToString
()
;
}
return string
.
Empty
;
}
set
{
if
((value == null) || (value.
Length
==
0
))
{
this
.
m_baseAddress
= null
;
}
else
{
try
{
this
.
m_baseAddress
= new
Uri
(value)
;
}
catch
(
Exception
exception1
)
{
throw
new
ArgumentException
(
"value"
, exception1
)
;
}
}
}
}
private
Uri
GetUri
(
string
path
)
{
Uri
uri1;
try
{
if
(
this
.
m_baseAddress
!= null)
{
uri1
= new
Uri
(
this
.
m_baseAddress, path
)
;
}
else
{
uri1
= new
Uri
(
path
)
;
}
if
(
this
.
m_requestParameters
== null)
{
return
uri1;
}
StringBuilder
builder1
= new
StringBuilder
()
;
string
text1
=
string
.
Empty
;
for
(
int
num1
=
0; num1
<
this
.
m_requestParameters
.
Count
; num1
++)
{
builder1
.
Append
(
text1
+
this
.
m_requestParameters
.
AllKeys
[
num1
] +
"="
+
this
.
m_requestParameters
[
num1
])
;
text1
=
"&"
;
}
UriBuilder
builder2
= new
UriBuilder
(
uri1
)
;
builder2
.
Query
=
builder1
.
ToString
()
;
uri1
=
builder2
.
Uri
;
}
catch
(
UriFormatException
)
{
uri1
= new
Uri
(
Path
.
GetFullPath
(
path
))
;
}
return
uri1;
}
}
}
/// <summary>
/// 测试类
/// </summary>
class
AppTest
{
int
_k
=
0;
int
_K
=
0;
static void
Main
()
{
AppTest a
= new
AppTest
()
;
Microshaoft
.
Utils
.
HttpWebClient x
= new
Microshaoft
.
Utils
.
HttpWebClient
()
;
a
.
_K
=
10;
//订阅 DataReceive 事件
x
.
DataReceive
+= new
Microshaoft
.
Utils
.
HttpWebClient
.
DataReceiveEventHandler
(
a
.
x_DataReceive
)
;
//订阅 ExceptionOccurrs 事件
x
.
ExceptionOccurrs
+= new
Microshaoft
.
Utils
.
HttpWebClient
.
ExceptionEventHandler
(
a
.
x_ExceptionOccurrs
)
;
x
.
ThreadProcessEnd
+= new
Microshaoft
.
Utils
.
HttpWebClient
.
ThreadProcessEventHandler
(
a
.
x_ThreadProcessEnd
)
;
string
F =
"http://localhost/download/phpMyAdmin-2.6.1-pl2.zip"
;
F =
"http://down6.flashget.com/flashget182cn.exe"
;
a
.
_F
= F
;
string
f
= F.
Substring
(F.
LastIndexOf
(
"/"
) +
1
)
;
//(new System.Threading.Thread(new System.Threading.ThreadStart(new ThreadProcessState(F, @"E:\temp\" + f, 10, x).StartThreadProcess))).Start();
x
.
DownloadFile
(F
, @
"d:\temp\" + f, a._K);
// x.DownloadFileChunk(F, @"E:\temp\" + f,15,34556);
System
.
Console
.
ReadLine
()
;
// string uploadfile = "e:\\test_local.rar";
// string str = x.UploadFileEx("http://localhost/phpmyadmin/uploadaction.php", "POST", uploadfile, "file1");
// System.Console.WriteLine(str);
// System.Console.ReadLine();
}
string
bs
=
""
;
//用于记录上次的位数
bool
b
=
false
;
private int
i
=
0;
private static object
_SyncLockObject
= new
object
()
;
string
_F;
string
_f;
private void
x_DataReceive
(
Microshaoft
.
Utils
.
HttpWebClient
Sender
, Microshaoft
.
Utils
.
DownLoadEventArgs e
)
{
if
(!
this
.
b
)
{
lock
(
_SyncLockObject
)
{
if
(!
this
.
b
)
{
System
.
Console
.
Write
(
System
.
DateTime
.
Now
.
ToString
() +
" 已接收数据: "
)
;
//System.Console.Write( System.DateTime.Now.ToString() + " 已接收数据: ");
this
.
b
=
true
;
}
}
}
string
f
=
e
.
DownloadState
.
FileName
;
if
(
e
.
DownloadState
.
AttachmentName
!= null)
f
=
System
.IO.
Path
.
GetDirectoryName
(
f
) +
@
"\" + e.DownloadState.AttachmentName;
this
.
_f
=
f;
using
(
System
.IO.
FileStream
sw
= new
System
.IO.
FileStream
(
f,
System
.IO.FileMode.OpenOrCreate
,
System
.IO.FileAccess.ReadWrite
,
System
.IO.FileShare.ReadWrite))
{
sw
.
Position
=
e
.
DownloadState
.
Position
;
sw
.
Write
(
e
.
DownloadState
.
Data
, 0, e
.
DownloadState
.
Data
.
Length
)
;
sw
.
Close
()
;
}
string
s
=
System
.
DateTime
.
Now
.
ToString
()
;
lock
(
_SyncLockObject
)
{
this
.
i
+=
e
.
DownloadState
.
Data
.
Length
;
System
.
Console
.
Write
(
bs
+
"\b\b\b\b\b\b\b\b\b\b"
+
i
+
" / "
+
Sender
.
FileLength
+
" 字节数据 "
+
s
)
;
//System.Console.Write(bs + i + " 字节数据 " + s);
this
.
bs
= new
string
(
'\b'
, Digits
(
i
) +
3
+
Digits
(
Sender
.
FileLength
) +
s
.
Length
)
;
}
}
int
Digits
(
int
n
)
//数字所占位数
{
n
=
System
.
Math
.
Abs
(
n
)
;
n
=
n
/
10;
int
i
=
1;
while
(
n
>
0
)
{
n
=
n
/
10;
i
++
;
}
return
i;
}
private void
x_ExceptionOccurrs
(
Microshaoft
.
Utils
.
HttpWebClient
Sender
, Microshaoft
.
Utils
.
ExceptionEventArgs e
)
{
System
.
Console
.
WriteLine
(
e
.
Exception
.
Message
)
;
//发生异常重新下载相当于断点续传,你可以自己自行选择处理方式
Microshaoft
.
Utils
.
HttpWebClient x
= new
Microshaoft
.
Utils
.
HttpWebClient
()
;
x
.
DownloadFileChunk
(
this
.
_F,
this
.
_f, e
.
DownloadState
.
Position
, e
.
DownloadState
.
Length
)
;
e
.
ExceptionAction
=
Microshaoft
.
Utils
.
ExceptionActions
.Ignore
;
}
private void
x_ThreadProcessEnd
(
Microshaoft
.
Utils
.
HttpWebClient
Sender
, Microshaoft
.
Utils
.
ThreadProcessEventArgs e
)
{
//if (e.thread.ThreadState == System.Threading.ThreadState.Stopped)
if
(
this
.
_k
++ ==
this
.
_K
-
1
)
System
.
Console
.
WriteLine
(
"\nend"
)
;
}
}