基础类:LoadFileEventArgs
public class LoadFileEventArgs : CancelEventArgs
{
public bool isAgain { get; set; }
public string Result { get; set; }
public DateTime CreateTime { get; set; }
public string Ftp_Head { get; set; }
public string Ftp_Dir_Model { get; set; }
public string Ftp_Dir_Project { get; set; }
public string Ftp_Dir_Name { get; set; }
public string Clint_Dir_Name { get; set; }
public string Clint_Dir { get; set; }
public string Clint_Dir_Next { get; set; }
public string Clint_File_Next { get; set; }
#region 断点续传
public Int64 SrcSize { get; set; }
public Int64 DesSize { get; set; }
public bool FileAppend { get; set; }
#endregion
}
照片移动辅助类
public class RmHelper
{
public string sourcePath { get; set; }
public string destPath { get; set; }
}
操作结果类
public class ResultInfo
{
public bool result { get; set; }
public string message { get; set; }
}
FTPHelper类
public class FTPHelper
{
LogHelper log = new LogHelper();
private static string FTPCONSTR = System.Configuration.ConfigurationManager.AppSettings["FTPCONSTR"];
private static string FTPUSERNAME = System.Configuration.ConfigurationManager.AppSettings["FTPUSERNAME"];
private static string FTPPASSWORD = System.Configuration.ConfigurationManager.AppSettings["FTPPASSWORD"];
private static string FTPMODEL = System.Configuration.ConfigurationManager.AppSettings["FTPMODEL"];
private static string CLINT_DIR_UPLOADSUCC = System.Configuration.ConfigurationManager.AppSettings["Clint_Dir_UploadSucc"];
private static string CLINT_DIR_UPLOADFAIL = System.Configuration.ConfigurationManager.AppSettings["Clint_Dir_UploadFail"];
private static string CLINT_DIR_UPLOADFAIL_AGAIN = System.Configuration.ConfigurationManager.AppSettings["Clint_Dir_UploadFail"];
private static FTPHelper instance = null;
private Queue<LoadFileEventArgs> pathQueue = new Queue<LoadFileEventArgs>();
public static FTPHelper Instance
{
get
{
if (instance == null)
{
if (instance == null)
instance = new FTPHelper();
}
return instance;
}
}
private delegate ResultInfo AsyncDelegate(LoadFileEventArgs args);
private event EventHandler<LoadFileEventArgs> onUploadFileFinishedEvent;
private event EventHandler<LoadFileEventArgs> UploadFailedEvent;
public event EventHandler onMonitorUploadEvent;
private bool IsWorking = false;
public bool CanStart = true;
private FTPHelper()
{
onUploadFileFinishedEvent += FtpHelper_onUploadFileFinishedEvent;
UploadFailedEvent += FtpHelper_UploadFailedEvent;
onMonitorUploadEvent += FtpHelper_onMonitorUploadEvent;
this.onMonitorUploadEvent?.Invoke(null, null);
}
public void InsertQueue(String directoryPath, string str = null)
{
bool b = false;
if (!string.IsNullOrEmpty(str))
b = true;
if (!System.IO.Directory.Exists(directoryPath)) return;
int index = directoryPath.LastIndexOf('\\');
string project = directoryPath.Substring(0, index);
int index2 = project.LastIndexOf('/');
string str_Result;
if (directoryPath.Substring(index + 1).Contains("NG"))
str_Result = "NG";
else
str_Result = "OK";
this.pathQueue.Enqueue(new LoadFileEventArgs
{
Ftp_Head = String.Format("ftp://{0}/{1}", FTPCONSTR, FTPMODEL),
Ftp_Dir_Model = FTPMODEL,
Ftp_Dir_Project = project.Substring(index2 + 1),
Ftp_Dir_Name = directoryPath.Substring(index + 1),
Clint_Dir_Name = directoryPath.Substring(index + 1),
Clint_Dir = directoryPath.Substring(0, index),
isAgain = b,
Result = str_Result,
CreateTime = Directory.GetCreationTime(directoryPath)
});
}
private void FtpHelper_onUploadFileFinishedEvent(object sender, LoadFileEventArgs e)
{
this.pathQueue.Dequeue();
RmHelper rm = new RmHelper();
rm.sourcePath = e.Clint_Dir + "/" + e.Clint_Dir_Name;
rm.destPath = CLINT_DIR_UPLOADSUCC + "/" +e.Ftp_Dir_Project +"/"+ e.Clint_Dir_Name;
Remove_Thread(rm);
}
private void FtpHelper_UploadFailedEvent(object sender, LoadFileEventArgs e )
{
this.pathQueue.Dequeue();
RmHelper rm = new RmHelper();
if (e.isAgain)
{
rm.sourcePath = e.Clint_Dir + "/" + e.Clint_Dir_Name;
rm.destPath = CLINT_DIR_UPLOADFAIL_AGAIN + "/" + e.Ftp_Dir_Project + "/" + e.Clint_Dir_Name;
}
else
{
rm.sourcePath = e.Clint_Dir + "/" + e.Clint_Dir_Name;
rm.destPath = CLINT_DIR_UPLOADFAIL + "/" + e.Ftp_Dir_Project + "/" + e.Clint_Dir_Name;
}
Remove_Thread(rm);
}
private void FtpHelper_onMonitorUploadEvent(object sender, EventArgs e)
{
Task.Factory.StartNew(() =>
{
while (true)
{
if (!IsWorking && this.pathQueue != null && this.pathQueue.Count > 0)
{
PerUpload();
System.Threading.Thread.Sleep(1000);
}
else if (!IsWorking && (this.pathQueue == null || this.pathQueue.Count == 0))
{
System.Threading.Thread.Sleep(1000);
}
else if (IsWorking)
{
System.Threading.Thread.Sleep(500);
}
}
});
}
private void PerUpload()
{
Task.Factory.StartNew(() =>
{
try
{
IsWorking = true;
AsyncDelegate uploadDelegate;
while (CanStart && this.pathQueue != null && this.pathQueue.Count > 0)
{
System.Threading.Thread.Sleep(100);
LoadFileEventArgs args = this.pathQueue.Peek();
uploadDelegate = new AsyncDelegate(instance.UpLoadDirectory);
IAsyncResult iasync = uploadDelegate.BeginInvoke(args, new AsyncCallback(FuncCallBack), null);
ResultInfo resultInfo = uploadDelegate.EndInvoke(iasync);
if (resultInfo.result)
{
bool b = PublicDB.InsertDirInfo(args);
if (b)
{
this.onUploadFileFinishedEvent?.Invoke(null, args);
log.WriteLine_Log(resultInfo.message);
}
else
{
this.UploadFailedEvent?.Invoke(null, args);
log.WriteLine_Log(args.Clint_Dir + "/" + args.Clint_Dir_Name+"文件上传成功,数据库保存记录失败!");
}
}
else
{
this.UploadFailedEvent?.Invoke(null, args);
log.WriteLine_Log(resultInfo.message);
}
}
}
catch (System.Exception ex)
{
log.WriteLine_Log(ex.Message);
}
finally
{
IsWorking = false;
}
});
}
#region 上传单个文件
public ResultInfo UpLoadFile(string localFile, string ftpPath)
{
ResultInfo resultInfo = new ResultInfo();
if (!File.Exists(localFile))
{
resultInfo.result = false;
resultInfo.message = "文件“" + localFile + "”不存在!上传失败!";
return resultInfo;
}
try
{
FileInfo fileInfo = new FileInfo(localFile);
FtpWebRequest reqFtp = (FtpWebRequest)FtpWebRequest.Create(ftpPath);
reqFtp.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);
reqFtp.KeepAlive = false;
reqFtp.Method = WebRequestMethods.Ftp.UploadFile;
reqFtp.UseBinary = true;
reqFtp.ContentLength = fileInfo.Length;
int buffLength = 2048;
byte[] buff = new byte[buffLength];
int contentLen;
FileStream fs = fileInfo.OpenRead();
Stream stream = reqFtp.GetRequestStream();
contentLen = fs.Read(buff, 0, buffLength);
while (contentLen != 0)
{
stream.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
}
stream.Close();
fs.Close();
resultInfo.result = true;
resultInfo.message = "文件“" + localFile + "”上传成功!";
return resultInfo;
}
catch (Exception ex)
{
resultInfo.result = false;
resultInfo.message = "文件“" + localFile + "”上传失败! 失败原因:" + ex.Message;
return resultInfo;
}
}
public ResultInfo UpLoadFile(LoadFileEventArgs arg)
{
LoadFileEventArgs args = new LoadFileEventArgs();
args.Clint_Dir = arg.Clint_Dir;
args.Clint_Dir_Name = arg.Clint_Dir_Name;
args.Clint_Dir_Next = arg.Clint_Dir_Next;
args.Clint_File_Next = arg.Clint_File_Next;
args.Ftp_Head = arg.Ftp_Head;
args.Ftp_Dir_Name = arg.Ftp_Dir_Name;
args.Ftp_Dir_Project = arg.Ftp_Dir_Project;
string localFile = args.Clint_Dir + "/" + args.Clint_Dir_Name + "/" + args.Clint_File_Next;
string ftpPath = args.Ftp_Head + "/" + args.Ftp_Dir_Project + "/" + args.Ftp_Dir_Name + @"/" + args.Clint_File_Next;
args.CreateTime = File.GetCreationTime(localFile);
Stream stream = null;
FileInfo fileInfo = new FileInfo(localFile);
args.SrcSize = fileInfo.Length;
ResultInfo resultInfo = new ResultInfo();
if (!File.Exists(localFile))
{
resultInfo.result = false;
resultInfo.message = "文件“" + localFile + "”不存在!上传失败!";
return resultInfo;
}
try
{
Boolean res = HandelMatchFile(args);
if (!res)
{
if (PublicDB.SelectPhotoInfo(args))
{
resultInfo.result = true;
resultInfo.message = "文件已上传!";
}
else
{
if (PublicDB.InsertPhotoInfo(args))
{
resultInfo.result = true;
resultInfo.message = "文件已上传!照片路径保存成功!";
}
else
{
resultInfo.result = false;
resultInfo.message = "文件已上传!照片路径保存失败!";
}
}
return resultInfo;
}
FtpWebRequest reqFtp = (FtpWebRequest)FtpWebRequest.Create(ftpPath);
reqFtp.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);
reqFtp.KeepAlive = false;
reqFtp.Method = WebRequestMethods.Ftp.UploadFile;
reqFtp.UseBinary = true;
reqFtp.ContentLength = fileInfo.Length;
int buffLength = 2048;
byte[] buff = new byte[buffLength];
int contentLen;
FileStream fs = fileInfo.OpenRead();
if (args.FileAppend)
{
reqFtp.Method = WebRequestMethods.Ftp.AppendFile;
reqFtp.ContentOffset = args.DesSize;
fs.Seek(args.SrcSize, 0);
}
using(stream = reqFtp.GetRequestStream())
{
while (true)
{
contentLen = fs.Read(buff, 0, buffLength);
if(contentLen == 0)
{
break;
}
stream.Write(buff, 0, contentLen);
}
stream.Dispose();
stream.Close();
fs.Close();
}
if (PublicDB.InsertPhotoInfo(args))
{
resultInfo.result = true;
resultInfo.message = "文件“" + localFile + "”上传成功!";
}
else
{
resultInfo.result = false;
resultInfo.message = "文件“" + localFile + "”上传成功!照片路径保存失败!";
}
return resultInfo;
}
catch (Exception ex)
{
resultInfo.result = false;
resultInfo.message = "文件“" + localFile + "”上传失败! 失败原因:" + ex.Message;
return resultInfo;
}
}
private Boolean HandelMatchFile(LoadFileEventArgs args)
{
Boolean res = true;
Tuple<int, int> tuple = CompareFileSize(args);
switch (tuple.Item1)
{
case 1:
break;
case 2:
args.FileAppend = true;
args.DesSize = tuple.Item2;
res = true;
break;
case 3:
res = false;
break;
default:
res = false;
break;
}
return res;
}
private Tuple<int, int> CompareFileSize(LoadFileEventArgs args)
{
string ftpPath = args.Ftp_Head + "/" + args.Ftp_Dir_Project + "/" + args.Ftp_Dir_Name + @"/" + args.Clint_File_Next;
String content = GetRemoteFileDetails(ftpPath);
if (String.IsNullOrEmpty(content))
return new Tuple<int, int>(1, 0);
string[] strs = content.Split(' ').Where(x => x != "").ToArray();
int fileSize = Convert.ToInt32(strs[2]);
if (fileSize < args.SrcSize)
return new Tuple<int, int>(2, fileSize);
return new Tuple<int, int>(3, fileSize);
}
private String GetRemoteFileDetails(String uri)
{
StreamReader sr = null;
String content = String.Empty;
FtpWebResponse response = null;
try
{
FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(uri);
ftp.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);
ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
ftp.UseBinary = true;
ftp.KeepAlive = false;
response = (FtpWebResponse)ftp.GetResponse();
using (sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
{
content = sr.ReadLine();
sr.Dispose();
sr.Close();
response.Close();
return content;
}
}
catch (System.Exception ex)
{
if (sr != null)
{
sr.Dispose();
sr.Close();
}
if (response != null)
{
response.Close();
}
return content;
}
}
#endregion
#region 上传文件夹
public ResultInfo UpLoadDirectory(string localDir, string ftpPath, string dirName)
{
ResultInfo resultInfo = new ResultInfo();
string dir = localDir + "/" + dirName;
if (!Directory.Exists(dir))
{
resultInfo.result = false;
resultInfo.message = "本地目录【" + dir + "】不存在!上传失败!";
return resultInfo;
}
if (!CheckDirectoryExist(ftpPath, dirName))
{
resultInfo = MakeDir(ftpPath, dirName);
if (!resultInfo.result)
{
return resultInfo;
}
}
List<List<string>> infos = GetDirDetails(dir);
for (int i = 0; i < infos[0].Count; i++)
{
resultInfo = UpLoadFile(dir + "/" + infos[0][i], ftpPath + "/" + dirName + @"/" + infos[0][i]);
if (!resultInfo.result)
{
break;
}
}
if (resultInfo.result)
{
for (int i = 0; i < infos[1].Count; i++)
{
resultInfo = UpLoadDirectory(dir, ftpPath + "/" + dirName, infos[1][i]);
if (!resultInfo.result)
{
break;
}
}
}
if (resultInfo.result)
{
resultInfo.message = "文件夹【" + dir + "】上传成功!";
}
return resultInfo;
}
public ResultInfo UpLoadDirectory(LoadFileEventArgs arg)
{
ResultInfo resultInfo = new ResultInfo();
LoadFileEventArgs args = new LoadFileEventArgs();
args.Clint_Dir = arg.Clint_Dir;
args.Clint_Dir_Name = arg.Clint_Dir_Name;
args.Clint_Dir_Next = arg.Clint_Dir_Next;
args.Clint_File_Next = arg.Clint_File_Next;
args.Ftp_Head = arg.Ftp_Head;
args.Ftp_Dir_Name = arg.Ftp_Dir_Name;
args.Ftp_Dir_Project = arg.Ftp_Dir_Project;
if (args.Clint_Dir_Next != null && args.Clint_Dir_Next != "")
{
args.Ftp_Dir_Project = args.Ftp_Dir_Project + "/" + args.Ftp_Dir_Name;
args.Ftp_Dir_Name = args.Clint_Dir_Next;
args.Clint_Dir = args.Clint_Dir + "/" + args.Clint_Dir_Name;
args.Clint_Dir_Name = args.Clint_Dir_Next;
}
string dir = args.Clint_Dir + "/" + args.Clint_Dir_Name;
if (!Directory.Exists(dir))
{
resultInfo.result = false;
resultInfo.message = "本地目录【" + dir + "】不存在!上传失败!";
return resultInfo;
}
if (!CheckDirectoryExist(args.Ftp_Head + "/" + args.Ftp_Dir_Project, args.Ftp_Dir_Name))
{
resultInfo = MakeDir(args.Ftp_Head + "/" + args.Ftp_Dir_Project, args.Ftp_Dir_Name);
if (!resultInfo.result)
{
return resultInfo;
}
}
List<List<string>> infos = GetDirDetails(dir);
for (int i = 0; i < infos[0].Count; i++)
{
args.Clint_File_Next = infos[0][i];
resultInfo = UpLoadFile(args);
if (!resultInfo.result)
{
break;
}
}
if (resultInfo.result)
{
for (int i = 0; i < infos[1].Count; i++)
{
args.Clint_Dir_Next = infos[1][i];
args.Clint_File_Next = null;
resultInfo = UpLoadDirectory(args);
if (!resultInfo.result)
{
break;
}
}
}
if (resultInfo.result)
{
resultInfo.message = "文件夹【" + dir + "】上传成功!";
}
GC.Collect();
return resultInfo;
}
void FuncCallBack(IAsyncResult res)
{
if (res.IsCompleted)
{
}
}
private bool CheckDirectoryExist(string ftpPath, string dirName)
{
bool flag = true;
try
{
FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(ftpPath + "/" + dirName);
ftp.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);
ftp.Method = WebRequestMethods.Ftp.ListDirectory;
FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
response.Close();
}
catch (Exception)
{
flag = false;
}
return flag;
}
public ResultInfo MakeDir(string ftpPath, string dirName)
{
ResultInfo resultinfo = new ResultInfo();
FtpWebRequest reqFTP;
try
{
string ui = (ftpPath + "/" + dirName).Trim();
reqFTP = (FtpWebRequest)FtpWebRequest.Create(ui);
reqFTP.Method = WebRequestMethods.Ftp.MakeDirectory;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream();
ftpStream.Close();
response.Close();
resultinfo.result = true;
resultinfo.message = "文件夹【" + dirName + "】创建成功!";
return resultinfo;
}
catch (Exception ex)
{
resultinfo.result = false;
resultinfo.message = "新建文件夹【" + dirName + "】时,发生错误:" + ex.Message;
return resultinfo;
}
}
private List<List<string>> GetDirDetails(string localDir)
{
List<List<string>> infos = new List<List<string>>();
try
{
infos.Add(Directory.GetFiles(localDir).ToList());
infos.Add(Directory.GetDirectories(localDir).ToList());
for (int i = 0; i < infos[0].Count; i++)
{
int index = infos[0][i].LastIndexOf("\\");
infos[0][i] = infos[0][i].Substring(index + 1);
}
for (int i = 0; i < infos[1].Count; i++)
{
int index = infos[1][i].LastIndexOf("\\");
infos[1][i] = infos[1][i].Substring(index + 1);
}
}
catch (Exception ex)
{
}
return infos;
}
#endregion
#region 文件上传结束 数据库保存&移动本地文件
private void Remove_Thread(RmHelper rm)
{
Thread th = new Thread(remove);
th.IsBackground = true;
th.Start(rm);
}
private void remove(object o)
{
RmHelper rm = o as RmHelper;
if (Directory.Exists(rm.sourcePath))
{
try
{
DirectoryInfo di = new DirectoryInfo(rm.sourcePath);
di.MoveTo(rm.destPath);
}
catch(Exception e)
{
log.WriteLine_Log(e.Message);
}
}
}
#endregion
}
上传
FTPHelper ftpHelper = FTPHelper.Instance;
ftpHelper.InsertQueue("路径", null);