异步下载:
public interface IPrimaryKey<T>
{
T GetKey();
} public class DownloadInfo : IPrimaryKey<string>
{
public string FtpResourceFilePath { get; set; } public string FileSaveLocalPath { get; set; } public bool IsDir { get; set; } public DateTime StartTime { get; set; } public int ProgressPercentage { get; set; } public string Speed { get; set; } public string GetKey()
{
return this.FtpResourceFilePath;
} public List<DownloadInfo> SubFiles { get; set; }
}
class Program
{
static readonly string FTP_USERNAME = string.Empty;
static readonly string FTP_PASSWORD = string.Empty;
static readonly string FTP_DOMAIN = string.Empty;
// default 1 seconds.
static readonly int FTP_REQUEST_TIMEOUT = ;
// default 1 seconds.
static readonly int FTP_REQUEST_READWRITERTIMEOUT = ; static Program()
{
FTP_REQUEST_TIMEOUT = Convert.ToInt32(ConfigurationManager.AppSettings.Get("FTP.Request.Timeout"));
FTP_REQUEST_READWRITERTIMEOUT = Convert.ToInt32(ConfigurationManager.AppSettings.Get("FTP.Request.ReadWriteTimeout"));
FTP_USERNAME = ConfigurationManager.AppSettings.Get("FTP.UserName");
FTP_PASSWORD = ConfigurationManager.AppSettings.Get("FTP.Password");
FTP_DOMAIN = ConfigurationManager.AppSettings.Get("FTP.Domain");
} static int DownloadCount = ;
static int CompleteCount = ; static void Main(string[] args)
{
// default max parallel connection count is two in the .net framework.
// sugesstion no over 1024.
// and you also can add config node in app.config
/* <configuration>
* <system.net>
* <connectionManagement>
* <add address="*" maxconnection="512"/>
* </connectionManagement>
* </system>
* </configuration>
*/
//System.Net.ServicePointManager.DefaultConnectionLimit = 512; string localRootPath = ConfigurationManager.AppSettings.Get("SaveRootPath"); List<DownloadInfo> rootFiles = GetSubFilesList(new DownloadInfo()
{
FtpResourceFilePath = "ftp://172.21.3.17//dd/MR",
FileSaveLocalPath = string.Concat(localRootPath, "~TEMP\\Test1")
}); DownloadFilesAsync(rootFiles); Console.ReadKey();
} private static void DownloadFilesAsync(List<DownloadInfo> items)
{
foreach (DownloadInfo task in items)
{
task.StartTime = DateTime.Now; if (task.IsDir)
{
task.SubFiles = GetSubFilesList(task); DownloadFilesAsync(task.SubFiles);
}
else
{
// try create the directory before donwload.
TryCreateDirectory(task.FileSaveLocalPath); // Uri :the resource paht which will be download.
// fileName :the dowload file save path;
CreateWebClient().DownloadFileAsync(new Uri(task.FtpResourceFilePath), task.FileSaveLocalPath, task);
}
}
} static WebClient CreateWebClient()
{
// 限制最多同时现在的线程数
LimitThreadAgain:
if (DownloadCount - CompleteCount > )
{
Thread.Sleep(); goto LimitThreadAgain;
} DownloadCount++; WebClient client = new WebClient();
client.Credentials = new NetworkCredential(FTP_USERNAME, FTP_PASSWORD, FTP_DOMAIN);
client.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(client_DownloadFileCompleted);
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged); return client;
} private static List<DownloadInfo> GetSubFilesList(DownloadInfo task)
{
List<DownloadInfo> subFiles = new List<DownloadInfo>(); FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(task.FtpResourceFilePath));
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
request.Credentials = new NetworkCredential(FTP_USERNAME, FTP_PASSWORD, FTP_DOMAIN);
request.UseBinary = true;
request.Timeout = FTP_REQUEST_TIMEOUT;
request.ReadWriteTimeout = FTP_REQUEST_READWRITERTIMEOUT; using (WebResponse response = request.GetResponse())
{
using (StreamReader responseStream = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default))
{
string line = responseStream.ReadLine();
while (line != null)
{
Console.WriteLine(line); string[] lineParitialArray = line.Split(new char[] { ' ' });
string theName = lineParitialArray[lineParitialArray.Length - ]; if (line.IndexOf("<DIR>") != -)
{
subFiles.Add(new DownloadInfo()
{
FtpResourceFilePath = string.Concat(task.FtpResourceFilePath, "/", theName),
FileSaveLocalPath = string.Concat(task.FileSaveLocalPath, "\\", theName),
IsDir = true
});
}
else
{
subFiles.Add(new DownloadInfo()
{
FtpResourceFilePath = string.Concat(task.FtpResourceFilePath, "/", theName),
FileSaveLocalPath = string.Concat(task.FileSaveLocalPath, "\\", theName),
IsDir = false
});
} line = responseStream.ReadLine();
}
}
} return subFiles;
} static void TryCreateDirectory(string filePath)
{
FileInfo fileInfo = new FileInfo(filePath);
if (!fileInfo.Directory.Exists)
{
try
{
fileInfo.Directory.Create();
}
catch (Exception ex)
{
Logger.Current.Error("an error thrown while create directory:\r\n{0}\r\n{1}", ex.Message, ex.StackTrace);
}
}
} static void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
DownloadInfo downloadInfo = e.UserState as DownloadInfo; downloadInfo.ProgressPercentage = e.ProgressPercentage;
double downloadTime = (DateTime.Now - downloadInfo.StartTime).TotalSeconds;
downloadInfo.Speed = GetFriendlyFileSize(e.BytesReceived / downloadTime, ); Console.WriteLine("download precentage:{0}-{1}-{2}", downloadInfo.ProgressPercentage, downloadInfo.Speed, downloadInfo.FtpResourceFilePath); Logger.Current.Debug(string.Format("download precentage:{0}-{1}-{2}", downloadInfo.ProgressPercentage, downloadInfo.Speed, downloadInfo.FtpResourceFilePath));
} static void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
if (e.Error.InnerException != null)
Logger.Current.Error(string.Format("download error:{0}\r\n{1}", e.Error.InnerException.Message, e.Error.InnerException.StackTrace));
else
Logger.Current.Error(string.Format("download error:{0}\r\n{1}", e.Error.Message, e.Error.StackTrace));
} DownloadInfo downloadInfo = e.UserState as DownloadInfo; Console.WriteLine("download complete:{0}", downloadInfo.FtpResourceFilePath);
Logger.Current.Debug(string.Format("download complete:{0}", downloadInfo.FtpResourceFilePath)); CompleteCount++;
} const double KB = ;
const double MR = KB * ;
const double GB = MR * ;
const double TB = MR * ;
const double PB = TB * ; static string GetFriendlyFileSize(double size, int decimals)
{
if (KB > size)
return string.Format("{0}B", Math.Round(size, decimals));
else if (MR > size)
return string.Format("{0}KB", Math.Round(size / KB, decimals));
else if (GB > size)
return string.Format("{0}MR", Math.Round(size / MR, decimals));
else if (TB > size)
return string.Format("{0}GB", Math.Round(size / GB, decimals));
else if (PB > size)
return string.Format("{0}TB", Math.Round(size / TB, decimals));
else
return string.Format("{0}PB", Math.Round(size / PB, decimals));
}
}
异步上传:
// uploading
#region uploading public class Program
{
public static void Main(string[] args)
{
FtpState state = new FtpState(); // the ftp url scheme like: ftp://
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri("ftp://172.21.*.1*//dd/SHFBGuidedInstaller_2014.5.31.0.zip"));
request.Method = WebRequestMethods.Ftp.UploadFile;
//request.Method = WebRequestMethods.Ftp.DownloadFile; request.Credentials = new NetworkCredential("dn", "new.1234", "domain"); state.Request = request;
state.FileName = @"C:\Users\dn\Desktop\SHFBGuidedInstaller_2014.5.31.0.zip";
//state.FileName = @"C:\Users\dn\Desktop\MR\SHFBGuidedInstaller_2014.5.31.0.zip"; // 获得WaitOne()对象
ManualResetEvent waitOjbect = state.OperationComplete; // 开始异步获取数据流
request.BeginGetRequestStream(
new AsyncCallback(EndGetStreamCallback),
state
); // 线程等待
waitOjbect.WaitOne(); if (state.OperationException != null)
{
throw state.OperationException;
}
else
{
Console.WriteLine("操作已经完成!");
}
} public class FtpState
{
private ManualResetEvent wait;
private FtpWebRequest request;
private string fileName;
private Exception opreationException = null;
private string statusDescription; public FtpState()
{
wait = new ManualResetEvent(false);
} public ManualResetEvent OperationComplete
{
get { return wait; }
} public FtpWebRequest Request
{
get { return request; }
set { request = value; }
} public string FileName
{
get { return fileName; }
set { fileName = value; }
} public Exception OperationException
{
get { return opreationException; }
set { opreationException = value; }
} public string StatusDescription
{
get { return statusDescription; }
set { statusDescription = value; }
}
} private static void EndGetStreamCallback(IAsyncResult result)
{
FtpState state = (FtpState)result.AsyncState; try
{
using (Stream requestStream = state.Request.EndGetRequestStream(result))
{
const int bufferLength = ;
byte[] buffer = new byte[bufferLength]; int count = ;
int readBytes = ; using (FileStream stream = File.OpenRead(state.FileName))
{
do
{
readBytes = stream.Read(buffer, , bufferLength); requestStream.Write(buffer, , readBytes); count += readBytes;
}
while (readBytes != );
} Console.WriteLine("写入{0}字节到数据流中", count); state.Request.BeginGetResponse(new AsyncCallback(EndGetResponseCallback), state);
}
}
catch (Exception ex)
{
Console.WriteLine("请求数据流失败!"); state.OperationException = ex;
state.OperationComplete.Set();
}
} private static void EndGetResponseCallback(IAsyncResult result)
{
FtpState state = (FtpState)result.AsyncState; try
{
FtpWebResponse response = (FtpWebResponse)state.Request.EndGetResponse(result);
response.Close(); state.StatusDescription = response.StatusDescription;
// 标记主线程结束
state.OperationComplete.Set();
}
catch (Exception ex)
{
Console.WriteLine("获取请求回应失败!");
state.OperationException = ex;
state.OperationComplete.Set();
}
} #endregion
}