//以文件上传为例,先说一下代码逻辑,有两个线程分别处理临时文件的获取,FTP文件上传,其中获取文件上传做了重复文件的判断。
public static readonly Queue<string> queue = new Queue<string>();
//临时文件队列,与文件队列互锁。
public static readonly Dictionary<string, List<string>> tempqueue = new Dictionary<string, List<string>>();
public static object obj = new object();
public static int flag = 0;
/// <summary>
/// 文件上传队列
/// </summary>
public static void CreateFileQuqe()
{
try
{
var filepath = HttpContext.Current.Server.MapPath("~");
filepath = filepath + @"\Services\TempFile";
#region
////重复文件批量删除
//new Task(() => DeleteRepeatFileiInTempFile(filepath)).Start();
//临时文件进入队列等待
new Task(() => AddFileToQuqe(filepath)).Start();
//开启线程处理上传文件
new Task(DealFtpUpload).Start();
#endregion
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 临时文件进入队列等待
/// </summary>
private static void AddFileToQuqe(string path)
{
//循环临时文件补充漏传
DirectoryInfo root = null;
//检测文件是否存在,不存在创建。
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
root = new DirectoryInfo(path);
}
else
{
root = new DirectoryInfo(path);
}
while (root != null)
{
Thread.Sleep(100);
if (root.GetFiles().Count() == 0)
{
Common.tempqueue.Clear();
}
else
{
lock (Common.obj)
{
foreach (FileInfo f in root.GetFiles())
{
if (GetFileHash(f.FullName, out string hashval))
{
if (Common.tempqueue.Keys.Contains(hashval))
{
List<string> list = Common.tempqueue[hashval];
var filepath = list.FirstOrDefault(m => m == f.FullName);
if (filepath == null)
{
list.Add(f.FullName);
Common.tempqueue[hashval] = list;
}
}
else
{
Common.tempqueue.Add(hashval, new List<string>() { f.FullName });
}
}
}
foreach (string d in Common.tempqueue.Keys)
{
List<string> list = Common.tempqueue[d];
if (list.Count == 1)
{
if (Common.queue.FirstOrDefault(m => m == list[0]) == null)
{
Common.queue.Enqueue(list[0]);
list.RemoveAt(0);
}
}
else
{
for (int i = 0; i < list.Count - 1; i++)
{
if (File.Exists(list[i]))
{
File.Delete(list[i]);
Debug.WriteLine(list[i]);
}
list.RemoveAt(i);
}
}
}
}
}
}
}
/// <summary>
/// 开启线程处理上传文件
/// </summary>
static void DealFtpUpload()
{
while (true)
{
Thread.Sleep(300);
if (Common.queue.Count > 0)
{
lock (Common.obj)
{
if (Common.queue.Count > 0)
{
//先取队列数据,判断是否存在;
string path = Common.queue.Dequeue();
//Debug.WriteLine((i++).ToString());
//Debug.WriteLine(path);
//数据库存在数据,临时文件也存在说明文件上传失败,重传
if (VerificationUpload(path, out string hashstr, out string holefilename))
{
var ftppath = Common.Ftp_Url + holefilename;
//文件哈希值存在数据库中,更新数据库的处理状态
if (UpdateVerificationUpload(path, hashstr))
{
//Ftp文件上传完毕,删除服务器临时文件。
File.Delete(path);
}
else
{
Common.queue.Enqueue(path);
}
}
//数据库不存在数据,临时文件也存在说明文件非法上传,删除文件,移除队列。
else
{
if (File.Exists(path))
{
File.Delete(path);
}
}
}
}
}
else
{
Thread.Sleep(2000);
lock (Common.obj)
{
if (Common.queue.Count <= 0)
{
//队里处理完毕,线程等待。
}
}
}
}
}
static bool VerificationUpload(string path, out string hashstr, out string holefilename)
{
if (GetFileHash(path, out string hashval))
{
string filename = Path.GetFileName(path);
//根据哈希值查询不重复添加
string existsql = $@"select Hash值 from table where Hash值 in('{hashval}')";
using (SqlDataReader read = SqlHelper.ExecuteReader(SqlHelper.SqlServer_100_Finance, CommandType.Text, existsql))
{
if (read.Read())
{
holefilename = filename;
hashstr = hashval;
return true;
}
else
{
hashstr = "";
holefilename = "";
return false;
}
}
}
else
{
hashstr = "";
holefilename = "";
return false;
}
}
/// <summary>
/// 获取文件哈希值
/// </summary>
/// <param name="path"></param>
/// <param name="hashval"></param>
/// <returns></returns>
static bool GetFileHash(string path, out string hashval)
{
if (File.Exists(path))
{
using (HashAlgorithm hash = HashAlgorithm.Create())
{
using (FileStream file1 = new FileStream(path, FileMode.Open))
{
byte[] hashByte1 = hash.ComputeHash(file1);
hashval = StringToHex.byteToHexStr(hashByte1).Trim();
file1.Close();
return true;
}
}
}
else
{
hashval = "";
return false;
}
}
static bool UpdateVerificationUpload(string path, string hashstr)
{
//using (SqlConnection conn = new SqlConnection(SqlHelper.SqlServer_100_Finance))
{
//conn.Open();
//SqlTransaction trans = conn.BeginTransaction();
if (FtpHelper.AsynchronousFtpUpLoader(path, out string ftppath))
{
var sql = $@"UPDATE table
SET
[处理状态] = '{nameof(处理状态.未处理)}',
[FTP路径] = '{ftppath}',
[上传时间] = '{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}'
WHERE Hash值 in ('{hashstr}')";
if (SqlHelper.ExecuteNonQuery(SqlHelper.SqlServer_100_Finance, CommandType.Text, sql) > 0)
{
//trans.Commit();
return true;
}
else
{
//trans.Rollback();
return false;
}
}
else
{
//trans.Rollback();
return false;
}
}
}