C#實現開發windows服務實現自動從FTP伺服器下載檔案(自行設定分/時執行)

蝶戀花雨發表於2016-06-10

最近在做一個每天定點從FTP自動下載節目.xml並更新到資料庫的功能。首先想到用 FileSystemWatcher來監控下載到某個目錄中的檔案是否發生改變,如果改變就執行相應的操作,然後用timer來設定隔多長時間來下載。後來又想想了。用windwos服務來實現吧。

效果圖:


執行的Log日誌:

INFO-2016/5/24 0:30:07--日誌內容為:0/30/7進行time觸發
INFO-2016/5/24 1:30:07--日誌內容為:1/30/7進行time觸發
INFO-2016/5/24 2:30:07--日誌內容為:2/30/7進行time觸發
INFO-2016/5/24 3:30:07--日誌內容為:3/30/7進行time觸發
INFO-2016/5/24 4:30:07--日誌內容為:4/30/7進行time觸發
INFO-2016/5/24 5:30:07--日誌內容為:5/30/7進行time觸發
INFO-2016/5/24 6:30:07--日誌內容為:6/30/7進行time觸發
INFO-2016/5/24 7:30:07--日誌內容為:7/30/7進行time觸發
INFO-2016/5/24 7:30:07--日誌內容為:TimerEvent 01
INFO-2016/5/24 7:30:07--日誌內容為:TimerEvent 01 :共獲取77個節目列表資訊成功。
INFO-2016/5/24 7:31:08--日誌內容為:伺服器與本地節目列表資訊進行對比開始。
INFO-2016/5/24 7:31:08--日誌內容為:得到要更新的節目列表共77個
INFO-2016/5/24 7:31:08--日誌內容為:FileEvent 01 :BTV-1(高清).xml檔案重新下載開始。
INFO-2016/5/24 7:31:08--日誌內容為:FileEvent 01 :BTV-1(高清).xml檔案內容已於2016/05/24 00:01進行changed並重新下載成功。
INFO-2016/5/24 7:31:08--日誌內容為:FileEvent 01 :BTV-1(高清).xml檔案下載後的修改時間開始與伺服器修改時間同步開始。
INFO-2016/5/24 7:31:08--日誌內容為:FileEvent 01 :BTV-1(高清).xml檔案下載後的修改時間開始與伺服器修改時間同步成功。
INFO-2016/5/24 7:31:08--日誌內容為:FileEvent 02 :CCTV-1(高清).xml檔案重新下載開始。
INFO-2016/5/24 7:31:08--日誌內容為:FileEvent 02 :CCTV-1(高清).xml檔案內容已於2016/05/24 00:01進行changed並重新下載成功。
INFO-2016/5/24 7:31:08--日誌內容為:FileEvent 02 :CCTV-1(高清).xml檔案下載後的修改時間開始與伺服器修改時間同步開始。
INFO-2016/5/24 7:31:08--日誌內容為:FileEvent 02 :CCTV-1(高清).xml檔案下載後的修改時間開始與伺服器修改時間同步成功。
INFO-2016/5/24 7:31:33--日誌內容為:FileEvent 77 :黑龍江衛視(高清).xml檔案重新下載開始。
INFO-2016/5/24 7:31:33--日誌內容為:FileEvent 77 :黑龍江衛視(高清).xml檔案內容已於2016/05/24 00:01進行changed並重新下載成功。
INFO-2016/5/24 7:31:33--日誌內容為:FileEvent 77 :黑龍江衛視(高清).xml檔案下載後的修改時間開始與伺服器修改時間同步開始。
INFO-2016/5/24 7:31:33--日誌內容為:FileEvent 77 :黑龍江衛視(高清).xml檔案下載後的修改時間開始與伺服器修改時間同步成功。
INFO-2016/5/24 8:31:08--日誌內容為:8/31/8進行time觸發
INFO-2016/5/24 9:31:08--日誌內容為:9/31/8進行time觸發
INFO-2016/5/24 10:31:08--日誌內容為:10/31/8進行time觸發
INFO-2016/5/24 11:31:08--日誌內容為:11/31/8進行time觸發
INFO-2016/5/24 12:31:08--日誌內容為:12/31/8進行time觸發
INFO-2016/5/24 13:31:08--日誌內容為:13/31/8進行time觸發
INFO-2016/5/24 14:31:08--日誌內容為:14/31/8進行time觸發
INFO-2016/5/24 15:31:08--日誌內容為:15/31/8進行time觸發
INFO-2016/5/24 16:31:08--日誌內容為:16/31/8進行time觸發
INFO-2016/5/24 17:31:08--日誌內容為:17/31/8進行time觸發
INFO-2016/5/24 18:31:08--日誌內容為:18/31/8進行time觸發
INFO-2016/5/24 19:31:08--日誌內容為:19/31/8進行time觸發
INFO-2016/5/24 20:31:08--日誌內容為:20/31/8進行time觸發
INFO-2016/5/24 21:31:08--日誌內容為:21/31/8進行time觸發
INFO-2016/5/24 22:31:08--日誌內容為:22/31/8進行time觸發
INFO-2016/5/24 23:31:08--日誌內容為:23/31/8進行time觸發

實現程式碼:

下載 ftplib.dll 然後專案中參照引用

using FtpLib;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Threading;

namespace WindowsService1
{
	public partial class Service1 : ServiceBase
	{
		private int _countFileChangeEvent = 0, _countTimerEvent = 0;

		private Thread ThreadDownLoad;

		public Service1()
		{
			InitializeComponent();
		}
		//http://blog.csdn.net/hwt0101/article/details/8514291
		//http://www.cnblogs.com/mywebname/articles/1244745.html
		//http://www.cnblogs.com/jzywh/archive/2008/07/23/filesystemwatcher.html
		//http://www.cnblogs.com/hfzsjz/archive/2011/01/07/1929898.html
		/// <summary>
		/// 服務啟動的操作
		/// </summary>
		/// <param name="args"></param>
		protected override void OnStart(string[] args)
		{
			try
			{
				EventLog.WriteEntry("監控伺服器與本地節目列表資訊執行緒任務開始");//在系統事件檢視器裡的應用程式事件裡來源的描述  
				WriteInLog("監控伺服器與本地節目列表資訊執行緒任務開始", false);
				System.Timers.Timer t = new System.Timers.Timer();
			//	t.Interval =  60000;
			 	t.Interval = 60 * 60 * 1000;      
				t.Elapsed += new System.Timers.ElapsedEventHandler(BeginDowLoad);//到達時間的時候執行事件;   
				t.AutoReset = true;//設定是執行一次(false)還是一直執行(true);   
				t.Enabled = true;//是否執行System.Timers.Timer.Elapsed事件;    
				t.Start();
			}
			catch (Exception ex)
			{
				System.Diagnostics.Trace.Write(ex.Message);
				throw ex;
			}
		}
		/// <summary>  
		/// 定時檢查,並執行方法  
		/// </summary>  
		/// <param name="source"></param>  
		/// <param name="e"></param>  
		public void BeginDowLoad(object source, System.Timers.ElapsedEventArgs e)
		{
			int intMinute = e.SignalTime.Minute;
			int intSecond = e.SignalTime.Second;
			int intHours = e.SignalTime.Hour;
			//設定 每天的07:30開始執行程式
			 WriteInLog(intHours+"/"+ intMinute + "/"+ intSecond + "進行time觸發", false);
			if (intHours == 07 ) ///定時設定,判斷分時秒  									  && intMinute == 10
			{
				try
				{
					System.Timers.Timer tt = (System.Timers.Timer)source;
					tt.Enabled = false;
					DownLoadTvListInfo();
					tt.Enabled = true;
				}
				catch (Exception err)
				{
					WriteInLog(err.Message, false);
				}
			}
		}

		public List<ChannelTvListInfo> listFTPFiles(string FTPAddress, string username, string password)
		{
			List<ChannelTvListInfo> listinfo = new List<ChannelTvListInfo>();
			using (FtpConnection ftp = new FtpConnection(FTPAddress, username, password))
			{
				ftp.Open();
				ftp.Login();
				foreach (var file in ftp.GetFiles("/"))
				{
					listinfo.Add(new ChannelTvListInfo
					{
						TVName = file.Name,
						LastWriteTime = Convert.ToDateTime(file.LastWriteTime).ToString("yyyy/MM/dd HH:mm")
					});
				}
				ftp.Dispose();
				ftp.Close();
			}
			return listinfo;
		}
		/// <summary>
		/// 服務停止的操作
		/// </summary>
		protected override void OnStop()
		{
			try
			{
				ThreadDownLoad.Abort();
				WriteInLog("監控伺服器與本地節目列表資訊執行緒任務停止", false);
				System.Diagnostics.Trace.Write("監控伺服器與本地節目列表資訊執行緒任務停止");
				EventLog.WriteEntry("監控伺服器與本地節目列表資訊執行緒任務停止");
			}
			catch (Exception ex)
			{
				System.Diagnostics.Trace.Write(ex.Message);
			}
		}

		private List<ChannelTvListInfo> lstNewTvInfo, lstOldTvInfo = new List<ChannelTvListInfo>();
		private void DownLoadTvListInfo()
		{
			_countTimerEvent++;
			WriteInLog(string.Format("TimerEvent {0}", _countTimerEvent.ToString("#00")), false);
			lstNewTvInfo = listFTPFiles("222.206.159.xx", "xx", "xx");

			WriteInLog(string.Format("TimerEvent {0} :共獲取{1}個節目列表資訊成功。", _countTimerEvent.ToString("#00"),lstNewTvInfo.Count), false);
			lstOldTvInfo = new List<ChannelTvListInfo>();

			DirectoryInfo TheFolder = new DirectoryInfo(@"D:\Hello\UpLoadImg\ChannelTvXML");
			foreach (FileInfo NextFile in TheFolder.GetFileSystemInfos())
			{
				lstOldTvInfo.Add(new ChannelTvListInfo { TVName = NextFile.Name, LastWriteTime = NextFile.LastWriteTime.ToString("yyyy/MM/dd HH:mm") });
			}
      Thread.Sleep(60000);
			ThreadDownLoad = new Thread(new ThreadStart(Test));
			ThreadDownLoad.Start();

			WriteInLog("伺服器與本地節目列表資訊進行對比開始。", false);
			System.Diagnostics.Trace.Write("執行緒任務開始");
		}

		public void Test()
		{
			try
			{
				var result = lstNewTvInfo.Except(lstOldTvInfo, new ProductComparer()).ToList();
				WriteInLog("得到要更新的節目列表共"+ result.Count+"個", false);
				if (result.Count > 0)
				{
					foreach (var item in result)
					{
						_countFileChangeEvent++;
						WriteInLog(string.Format("FileEvent {0} :{1}檔案重新下載開始。", _countFileChangeEvent.ToString("#00"),
								item.TVName), false);

						new FtpHelper().DownloadFtpFile("xx", "xx", "222.206.159.xx", @"D:\Hello\UpLoadImg\ChannelTvXML", item.TVName);

						WriteInLog(string.Format("FileEvent {0} :{1}檔案內容已於{2}進行{3}", _countFileChangeEvent.ToString("#00"),
                                item.TVName, item.LastWriteTime, "changed並重新下載成功。"), false);

						WriteInLog(string.Format("FileEvent {0} :{1}檔案下載後的修改時間開始與伺服器修改時間同步開始。", _countFileChangeEvent.ToString("#00"),
				item.TVName), false);
						File.SetLastWriteTime(@"D:\Hello\UpLoadImg\ChannelTvXML\" + item.TVName,
							Convert.ToDateTime(new FtpHelper().GetDateTimestamp("222.206.159.xx", item.TVName, "xx", "quanmeiti").xx("yyyy/MM/dd hh:mm tt")));

						WriteInLog(string.Format("FileEvent {0} :{1}檔案下載後的修改時間開始與伺服器修改時間同步成功。", _countFileChangeEvent.ToString("#00"),
				item.TVName), false);

					}
				}
				else
				{
					WriteInLog("暫無伺服器電視節目列表更新", false);
				}

			}
			catch { }
			Thread.Sleep(60000);
		}

		/// <summary>
		/// 寫入檔案操作
		/// </summary>
		/// <param name="msg">寫入內容</param>
		/// <param name="IsAutoDelete">是否刪除</param>
		private void WriteInLog(string msg, bool IsAutoDelete)
		{
			try
			{
				string logFileName = @"D:\Hello\UpLoadImg\ChannelLog\DownTvList_" + DateTime.Now.ToString("yyyyMMdd") + "_log.txt" + ""; // 檔案路徑

				FileInfo fileinfo = new FileInfo(logFileName);
				if (IsAutoDelete)
				{
					if (fileinfo.Exists && fileinfo.Length >= 1024)
					{
						fileinfo.Delete();
					}
				}
				using (FileStream fs = fileinfo.OpenWrite())
				{
					StreamWriter sw = new StreamWriter(fs);
					sw.BaseStream.Seek(0, SeekOrigin.End);
					sw.Write("INFO-" + DateTime.Now.ToString() + "--日誌內容為:" + msg + "\r\n");
					sw.Flush();
					sw.Close();
				}
			}
			catch (Exception ex)
			{
				ex.ToString();
			}
		}
	}

}

實現從FTP下載檔案方法

	/// <summary>
		///從ftp伺服器上下載檔案的功能
		/// </summary>
		/// <param name="userId"></param>
		/// <param name="pwd"></param>
		/// <param name="ftpUrl">ftp地址</param>
		/// <param name="filePath"></param>
		/// <param name="fileName"></param>
		public void DownloadFtpFile(string userId, string pwd, string ftpUrl, string filePath, string fileName)
		{
			FtpWebRequest reqFTP = null;
			FtpWebResponse response = null;
			try
			{
				String onlyFileName = Path.GetFileName(fileName);

				string downFileName = filePath + "\\" + onlyFileName;
				string url = "ftp://" + ftpUrl + "/" + fileName;
				if (File.Exists(downFileName))
				{
					DeleteDir(downFileName);
				}

				FileStream outputStream = new FileStream(downFileName, FileMode.Create);

				reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(url));
				reqFTP.Credentials = new NetworkCredential(userId, pwd);
				reqFTP.UseBinary = true;
				reqFTP.UsePassive = true;
				reqFTP.KeepAlive = true;
				reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
				response = (FtpWebResponse)reqFTP.GetResponse();

 
				Stream ftpStream = response.GetResponseStream();
				long cl = response.ContentLength;
				int bufferSize = 2048;
				int readCount;
				byte[] buffer = new byte[bufferSize];
				readCount = ftpStream.Read(buffer, 0, bufferSize);
				while (readCount > 0)
				{
					outputStream.Write(buffer, 0, readCount);
					readCount = ftpStream.Read(buffer, 0, bufferSize);
				}
				ftpStream.Close();
				outputStream.Close();
				response.Close();


			}
			catch (Exception ex)
			{
				throw ex;
			}
		}


設定widnwos服務就不多介紹了。如下圖:






相關文章