C#开发windows服务实现自动从FTP服务器下载文件
作者:蝶恋花雨 发布时间:2022-08-26 04:11:41
标签:C#,FTP,下载文件
最近在做一个每天定点从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服务就不多介绍了。如下图:
来源:https://blog.csdn.net/kongwei521/article/details/51626589


猜你喜欢
- Java基础 Servlet * 详解 1 概念:Servlet * ,用来监听web容器的一些对象状态的变化,主要是Servle
- 前言使用输入框时产品常常会有一些需求,比如123456789变成123-456-789或者限制一些字符的输入等等。很多时候都是网上搜索就完事
- Spring中有很多继承于aware中的接口,这些接口到底是做什么用到的。aware,翻译过来是知道的,已感知的,意识到的,所以这些接口从字
- 在Ubuntu Android简单介绍硬件抽象层(HAL)一文中,
- 很多方法请看官网地址:hutool官网地址脚本之家下载:https://www.jb51.net/softs/549331.html简介Hu
- java缓冲流本身不具IO功能,只是在别的流上加上缓冲提高效率,像是为别的流装上一种包装。当对文件或其他目标频繁读写或操作效率低,效能差。这
- 详细步骤首先在pom.xml文件中做一些修改:之前打war包需要修改打包方式,这次不需要了,因为默认就是 jar 包指定最终打成jar包的名
- 本文实例讲述了Android实现跑马灯效果的方法。分享给大家供大家参考。具体如下:运行效果截图如下:直接在布局里写代码就好了:<Tex
- 程序的结构分类:顺序结构:按照写代码的顺序 一次执行选择结构:根据条件的不同有选择的执行不同的代码循环结构:在一定条件下 反复执行某一片代码
- 前面文章讲述了Android手机与BLE终端之间的通信,而最常见的BLE终端应该是苹果公司倡导的iBeacon基站。iBeacon技术基于B
- Android 设置颜色的方法总结Android中有几种设置界面背景及文字颜色的方法,下面由浅入深分别介绍Android中设置颜色的几种方法
- 1、使用org.springframework.beans.BeanUtils.copyProperties方法进行对象之间属性的赋值,避免
- 该注解用于将 Controller 的方法返回的对象,通过 HttpMessageConverter 接口转换为指定格式的数据如:json,
- 使用Socket实现多人聊天应用,供大家参考,具体内容如下 在讲scoket通信器先可以先了解一下网络协议手机能够使用联网功能是因
- 有人在社区问到:C#调用Oracle中自定义函数的返回值时,无法正常调用。但在PL/SQL中正常调用返回。于是动手一试:1、准备函数(Ora
- 现在我们常见的一些关于Linux的系统很多,但是使用的更多的一般都是CentOS和Ubuntu,今天我就来记录一下关于centos下java
- APP启动速度非常重要,APP启动速度慢,可能会造成用户体验不良好,尤其是在最近用Android studio之后,如果长时间不打开app,
- 笔记在微服务中,若想要使用远程调用,需要引入spring-cloud-starter-openfeign(在使用注册中心的环境下)<d
- 先讲一下java中的反射:反射就是将类别的各个组成部分进行剖析,可以得到每个组成部分,就可以对每一部分进行操作反射机制应用场景:逆向代码、动
- hystrixDashboard服务监控除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboar