diff --git a/KsatSupplymentLibrary/App.config b/KsatSupplymentLibrary/App.config new file mode 100644 index 0000000..16a26b2 --- /dev/null +++ b/KsatSupplymentLibrary/App.config @@ -0,0 +1,27 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/KsatSupplymentLibrary/KsatSupplymentLibrary.csproj b/KsatSupplymentLibrary/KsatSupplymentLibrary.csproj new file mode 100644 index 0000000..3d326cc --- /dev/null +++ b/KsatSupplymentLibrary/KsatSupplymentLibrary.csproj @@ -0,0 +1,96 @@ + + + + + + Debug + AnyCPU + {3C90349C-2148-4D79-9881-7B3474EA8AF7} + Library + Properties + Ksat.Supplyment.Library + KsatSupplymentLibrary + v4.5 + 512 + true + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.dll + + + ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.SqlServer.dll + + + ..\packages\SQLite.CodeFirst.1.7.0.34\lib\net45\SQLite.CodeFirst.dll + + + + + + + ..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.115.5\lib\net45\System.Data.SQLite.dll + + + ..\packages\System.Data.SQLite.EF6.1.0.115.5\lib\net45\System.Data.SQLite.EF6.dll + + + ..\packages\System.Data.SQLite.Linq.1.0.115.5\lib\net45\System.Data.SQLite.Linq.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + + + + + + + + \ No newline at end of file diff --git a/KsatSupplymentLibrary/Model/CodeFirstDbContext.cs b/KsatSupplymentLibrary/Model/CodeFirstDbContext.cs new file mode 100644 index 0000000..9a7cada --- /dev/null +++ b/KsatSupplymentLibrary/Model/CodeFirstDbContext.cs @@ -0,0 +1,39 @@ +using System; +using System.Data.Entity; +using System.Linq; + +namespace Ksat.Supplyment.Library.Model +{ + public class CodeFirstDbContext : DbContext + { + //您的上下文已配置为从您的应用程序的配置文件(App.config 或 Web.config) + //使用“CodeFirstDbContext”连接字符串。默认情况下,此连接字符串针对您的 LocalDb 实例上的 + //“Ksat.Supplyment.Library.Model.CodeFirstDbContext”数据库。 + // + //如果您想要针对其他数据库和/或数据库提供程序,请在应用程序配置文件中修改“CodeFirstDbContext” + //连接字符串。 + public CodeFirstDbContext() : base(@"name = sqlite") + { + } + + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + modelBuilder.Entity().ToTable("UploadCaches").HasKey(p => p.Id); + modelBuilder.Entity().ToTable("UploadCancels").HasKey(p => p.Id); + modelBuilder.Entity().ToTable("UploadFinishs").HasKey(p => p.Id); + Database.SetInitializer(new SQLite.CodeFirst.SqliteCreateDatabaseIfNotExists(modelBuilder)); + } + + //为您要在模型中包含的每种实体类型都添加 DbSet。有关配置和使用 Code First 模型 + //的详细信息,请参阅 https://blog.csdn.net/wucdsg/article/details/78895366 + public virtual DbSet UploadCaches { get; set; } + public virtual DbSet UploadCancels { get; set; } + public virtual DbSet UploadFinishs { get; set; } + } + + //public class MyEntity + //{ + // public int Id { get; set; } + // public string Name { get; set; } + //} +} \ No newline at end of file diff --git a/KsatSupplymentLibrary/Model/Uploader/UploadCache.cs b/KsatSupplymentLibrary/Model/Uploader/UploadCache.cs new file mode 100644 index 0000000..ad6172f --- /dev/null +++ b/KsatSupplymentLibrary/Model/Uploader/UploadCache.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Ksat.Supplyment.Library.Model.Uploader +{ + public class UploadCache + { + [Key] + public int Id { get; set; } + + /// + /// 属于哪个上传任务 + /// + [Required] + public string UploaderID { get; set; } + + [Required] + public DateTime CreateAt { get; set; } + + /// + /// 最后一次上传时间 + /// + public DateTime RetryAt { get; set; } + + /// + /// 尝试次数 + /// + public int RetryCount { get; set; } + + /// + /// 错误信息 + /// + public string ErrorInfo { get; set; } + + /// + /// 上传相关数据 + /// + public string RequestData { get; set; } + } +} diff --git a/KsatSupplymentLibrary/Model/Uploader/UploadCancel.cs b/KsatSupplymentLibrary/Model/Uploader/UploadCancel.cs new file mode 100644 index 0000000..683587c --- /dev/null +++ b/KsatSupplymentLibrary/Model/Uploader/UploadCancel.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Ksat.Supplyment.Library.Model.Uploader +{ + public class UploadCancel + { + [Key] + public int Id { get; set; } + + /// + /// 属于哪个上传任务 + /// + [Required] + public string UploaderID { get; set; } + + [Required] + public DateTime CreateAt { get; set; } + + /// + /// 最后一次上传时间 + /// + public DateTime RetryAt { get; set; } + + /// + /// 错误信息 + /// + public string ErrorInfo { get; set; } + + /// + /// 尝试次数 + /// + public int RetryCount { get; set; } + + /// + /// 上传相关数据 + /// + public string RequestData { get; set; } + } +} diff --git a/KsatSupplymentLibrary/Model/Uploader/UploadFinish.cs b/KsatSupplymentLibrary/Model/Uploader/UploadFinish.cs new file mode 100644 index 0000000..0425418 --- /dev/null +++ b/KsatSupplymentLibrary/Model/Uploader/UploadFinish.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Ksat.Supplyment.Library.Model.Uploader +{ + public class UploadFinish + { + [Key] + public int Id { get; set; } + + /// + /// 属于哪个上传任务 + /// + [Required] + public string UploaderID { get; set; } + + [Required] + public DateTime CreateAt { get; set; } + + /// + /// 最后一次上传时间 + /// + public DateTime RetryAt { get; set; } + + /// + /// 尝试次数 + /// + public int RetryCount { get; set; } + + /// + /// 上传相关数据 + /// + public string RequestData { get; set; } + } +} diff --git a/KsatSupplymentLibrary/Model/Uploader/UploadModel.cs b/KsatSupplymentLibrary/Model/Uploader/UploadModel.cs new file mode 100644 index 0000000..3128fea --- /dev/null +++ b/KsatSupplymentLibrary/Model/Uploader/UploadModel.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Ksat.Supplyment.Library.Model.Uploader +{ + public class UploadModel + { + public DateTime CreateAt; + + /// + /// 最后一次上传时间 + /// + public DateTime RetryAt; + + /// + /// 尝试次数 + /// + public int RetryCount; + + /// + /// 错误信息 + /// + public string ErrorInfo; + + public T Request; + } +} diff --git a/KsatSupplymentLibrary/Properties/AssemblyInfo.cs b/KsatSupplymentLibrary/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..289b509 --- /dev/null +++ b/KsatSupplymentLibrary/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("KsatSupplymentLibrary")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("KsatSupplymentLibrary")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("3c90349c-2148-4d79-9881-7b3474ea8af7")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/KsatSupplymentLibrary/Uploader/IUploaderOperator.cs b/KsatSupplymentLibrary/Uploader/IUploaderOperator.cs new file mode 100644 index 0000000..932935f --- /dev/null +++ b/KsatSupplymentLibrary/Uploader/IUploaderOperator.cs @@ -0,0 +1,39 @@ +using Ksat.Supplyment.Library.Model.Uploader; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Ksat.Supplyment.Library.Uploader +{ + + public interface IUploaderOperator + { + + /// + /// 上传数据 + /// + IUploaderRequest UploadData(T data); + + + + T ConvertCacheToRequest(string cache); + string ConvertRequestToCachel(T requestData); + + /// + /// 任务开始前,判断任务是否要开始 + /// + /// + /// + /// + bool ShouldStartRequest(UploadModel requestModel, out string cancelReason); + + /// + /// 任务失败以后,判断是否需要重试 + /// + /// + /// + /// + bool ShouldRetryRequest(UploadModel requestModel, out string cancelReason); + } +} \ No newline at end of file diff --git a/KsatSupplymentLibrary/Uploader/IUploaderRequest.cs b/KsatSupplymentLibrary/Uploader/IUploaderRequest.cs new file mode 100644 index 0000000..0757e98 --- /dev/null +++ b/KsatSupplymentLibrary/Uploader/IUploaderRequest.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Ksat.Supplyment.Library.Model.Uploader; + +namespace Ksat.Supplyment.Library.Uploader +{ + public delegate void UploadFinishHandler(object sender, bool success, string reason) ; + + public interface IUploaderRequest + { + /// + /// 请求数据 + /// + T RequestData { get; set; } + + /// + /// 开始上传任务 + /// + void Start(); + + /// + /// 停止上传任务 + /// + void Cancel(); + + /// + /// 上传完成事件 + /// + event UploadFinishHandler UploadFinish; + } +} \ No newline at end of file diff --git a/KsatSupplymentLibrary/Uploader/Uploader.cs b/KsatSupplymentLibrary/Uploader/Uploader.cs new file mode 100644 index 0000000..ddbb11c --- /dev/null +++ b/KsatSupplymentLibrary/Uploader/Uploader.cs @@ -0,0 +1,412 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using Ksat.Supplyment.Library.Model.Uploader; +using Ksat.Supplyment.Library.Model; + +namespace Ksat.Supplyment.Library.Uploader +{ + public class Uploader : IDisposable + { + /// + /// 上传操作执行者 + /// + internal IUploaderOperator mOperator; + + /// + /// 上传数据队列 + /// + private readonly ConcurrentQueue> mDatas = new ConcurrentQueue>(); + + /// + /// 交换数据队列 + /// + private readonly ConcurrentQueue> mSwapDatas = new ConcurrentQueue>(); + + /// + /// 上传请求 + /// + private readonly LinkedList, UploadModel>> mRequests = new LinkedList, UploadModel>>(); + + private readonly System.Threading.Thread mDatasWorkerThread; + + /// + /// 最大队列长度 + /// + public int MaxOperatingQueueSize = 5; + + /// + /// 同时上传的数量 + /// + public int MaxCocurrentTaskCount = 2; + + private int mIsCanceled = 0; + + /// + /// 任务唯一标识,与数据库中UploaderID对应 + /// + private string mTaskIdentify; + + private Timer mSwapClearTimer; + + + public Uploader(string ID, IUploaderOperator op) + { + if (op == null) + throw new System.ArgumentNullException(); + this.mTaskIdentify = ID; + this.mOperator = op; + //sLog = LoggerFactory.ForContext("Uploader:" + this.mTaskIdentify); + mDatasWorkerThread = new System.Threading.Thread(uploadWorker) + { + Name = "upload worker", + IsBackground = true + }; + mDatasWorkerThread.Start(); + + mSwapClearTimer = new Timer((x) => + { + var toDBs = new List>(); + + UploadModel d; + while (mSwapDatas.TryDequeue(out d)) + { + toDBs.Add(d); + } + if (toDBs.Count != 0) + cacheRequest(toDBs); + }, null, 4000, 4000); + } + + public void Dispose() + { + Interlocked.Exchange(ref mIsCanceled, 1); + try + { + mSwapClearTimer.Dispose(); + mDatasWorkerThread.Abort(); + + List> toCache = new List>(); + + ///取消当前上传中任务, + lock (mRequests) + { + mRequests.ToList().ForEach((r) => + { + r.Item1.UploadFinish -= Req_OnRequestFinished; + r.Item1.Cancel(); + r.Item2.ErrorInfo = "上传程序中止,任务cancel"; + toCache.Add(r.Item2); + }); + } + mDatas.ToList().ForEach((d) => toCache.Add(d)); + mSwapDatas.ToList().ForEach((d) => toCache.Add(d)); + cacheRequest(toCache); + } + catch + { + } + } + + /// + /// 加入到上传任务队列 + /// + /// + /// + private void enqueRequest(TReq req, UploadModel requestModel) where TReq : IUploaderRequest + { + req.UploadFinish += Req_OnRequestFinished; + lock (mRequests) + { + mRequests.AddLast(new Tuple, UploadModel>(req, requestModel)); + } + } + + /// + /// 从上传任务队列中移除 + /// + /// + /// + private UploadModel dequeRequest(TReq req) where TReq : IUploaderRequest + { + req.UploadFinish -= Req_OnRequestFinished; + UploadModel reqModel = null; + lock (mRequests) + { + var found = mRequests.FirstOrDefault((x) => x.Item1 == req as IUploaderRequest); + if (found != null) + { + reqModel = found.Item2; + mRequests.Remove(found); + } + } + return reqModel; + } + + /// + /// 任务完成回调 + /// + /// + /// + private void Req_OnRequestFinished(object sender, bool success, string reason) + { + var request = sender as IUploaderRequest; + var x = (request.RequestData); + var reqModel = dequeRequest(request); + + if (reqModel == null) + { + //sLog.Formf($"no request found:{request.RequestData}"); + return; + } + reqModel.ErrorInfo = reason; + + + //sLog.Formf($"{reqModel.Request} finished:{success}"); + string cancelRetryReason = null; + if (success) + using (var db = new CodeFirstDbContext()) + { + db.UploadFinishs.Add(new UploadFinish + { + CreateAt = reqModel.CreateAt, + RetryAt = reqModel.RetryAt, + RetryCount = reqModel.RetryCount, + RequestData = mOperator.ConvertRequestToCachel(reqModel.Request), + UploaderID = mTaskIdentify + }); + db.SaveChanges(); + + } + else if (mOperator.ShouldRetryRequest(reqModel, out cancelRetryReason)) + { + + if (mDatas.Count >= MaxOperatingQueueSize) + { + mSwapDatas.Enqueue(reqModel); + } + else + { + mDatas.Enqueue(reqModel); + } + } + else + { + using (var db = new CodeFirstDbContext()) + { + db.UploadCancels.Add(new UploadCancel + { + CreateAt = reqModel.CreateAt, + RetryAt = reqModel.RetryAt, + RetryCount = reqModel.RetryCount, + RequestData = mOperator.ConvertRequestToCachel(reqModel.Request), + ErrorInfo = "Task cancel Retry:" + cancelRetryReason ?? "No Reason", + UploaderID = mTaskIdentify + });; + db.SaveChanges(); + } + } + + Console.WriteLine($"{DateTime.UtcNow.ToString("mm:ss.fff")} task {x} result:{success}"); + //throw new NotImplementedException(); + } + + /// + /// 上传worker + /// + private void uploadWorker() + { + while (!Interlocked.Equals(mIsCanceled, 1)) + { + int reqCount; + lock (mRequests) + reqCount = mRequests.Count; + if (reqCount >= MaxCocurrentTaskCount) + { + System.Threading.Thread.Sleep(10); + Console.WriteLine($"{DateTime.UtcNow.ToString("mm:ss.fff")} task exceed {MaxCocurrentTaskCount}, waiting"); + continue; + } + int newRequestCount = MaxCocurrentTaskCount - reqCount; + + //只尝试加载一次cache + bool hasGotCache = false; + for (int i = 0; i < newRequestCount;) + { + UploadModel d; + if (mDatas.TryDequeue(out d)) + { + string donotStartReason; + if (!mOperator.ShouldStartRequest(d, out donotStartReason)) + { + using (var db = new CodeFirstDbContext()) + { + db.UploadCancels.Add(new UploadCancel + { + CreateAt = d.CreateAt, + RetryAt = d.RetryAt, + RetryCount = d.RetryCount, + RequestData = mOperator.ConvertRequestToCachel(d.Request), + ErrorInfo = "Task cancel Start:" + donotStartReason ?? "No Reason", + UploaderID = mTaskIdentify + }); ; + db.SaveChanges(); + } + continue; + } + d.RetryAt = DateTime.Now; + d.RetryCount++; + var req = mOperator.UploadData(d.Request); + enqueRequest(req, d); + ThreadPool.QueueUserWorkItem(new WaitCallback((o) => req.Start())); + //new System.Threading.Thread(req.Start).Start(); + //req.Start(); + i++; + continue; + } + else if (!hasGotCache) + { + hasGotCache = true; + var caches = getCaches(MaxOperatingQueueSize); + if (caches.Count == 0) + { + //cache也没有任务了 + break; + } + caches.ForEach((t) => { mDatas.Enqueue(t); }); + continue; + } + } + } + } + + private void cacheRequest(List datas) + { + using (var db = new CodeFirstDbContext()) + { + //sLog.Formf($"cache requests,{datas.Count()}"); + var caches = datas.Select((data) => + new UploadCache + { + UploaderID = mTaskIdentify, + CreateAt = DateTime.Now, + RetryAt = new DateTime(1970, 1, 1), + RetryCount = 0, + ErrorInfo = "", + RequestData = mOperator.ConvertRequestToCachel(data) + } + ); + db.UploadCaches.AddRange(caches); + db.SaveChanges(); + } + } + + /// + /// 缓存请求数据到数据库 + /// + /// + private void cacheRequest(List> datas) + { + //sLog.Formf($"cache requests count,{datas.Count()}"); + using (var db = new CodeFirstDbContext()) + { + var caches = datas.Select((data) => + new UploadCache + { + UploaderID = mTaskIdentify, + CreateAt = data.CreateAt, + RetryAt = data.RetryAt, + RetryCount = data.RetryCount, + ErrorInfo = data.ErrorInfo, + RequestData = mOperator.ConvertRequestToCachel(data.Request) + } + ); + db.UploadCaches.AddRange(caches); + db.SaveChanges(); + } + } + + /// + /// 从数据库中提取指定数量的请求数据 + /// + /// + /// + private List> getCaches(int number) + { + var ret = new List>(); + var toGet = number; + UploadModel model; + + while (toGet > 0 && mSwapDatas.TryDequeue(out model)) + { + ret.Add(model); + toGet--; + } + + using (var db = new CodeFirstDbContext()) + { + var caches = from c in db.UploadCaches + orderby c.RetryAt ascending + where c.UploaderID == this.mTaskIdentify + select c; + var x = caches.Take(toGet).ToList(); + //从数据库中移除 + db.UploadCaches.RemoveRange(x); + db.SaveChanges(); + var modelsFromDB = x.Select((data) => + new UploadModel + { + CreateAt = data.CreateAt, + RetryAt = data.RetryAt, + RetryCount = data.RetryCount, + ErrorInfo = data.ErrorInfo, + Request = mOperator.ConvertCacheToRequest(data.RequestData) + } + ).ToList(); + + ret.AddRange(modelsFromDB); + } + + //if (ret.Count() != 0) + //sLog.Formf($"get {number} cache return {ret.Count()}"); + return ret; + } + + /// + /// 添加上传请求 + /// + public void AddUploadRequest(T data) + { + if (!Interlocked.Equals(mIsCanceled, 1)) + { + + var requestData = new UploadModel + { + CreateAt = DateTime.Now, + RetryAt = new DateTime(1970, 1, 1), + RetryCount = 0, + ErrorInfo = "", + Request = data + }; + if (mDatas.Count >= MaxOperatingQueueSize) + { + //sLog.Formf($"add request to swap,{data}"); + mSwapDatas.Enqueue(requestData); + } + else + { + //sLog.Formf($"add request to queue,{data}"); + mDatas.Enqueue(requestData); + } + } + else + { + //sLog.Formf("task canceled"); + cacheRequest(new List() { data }); + } + } + } +} \ No newline at end of file diff --git a/KsatSupplymentLibrary/flow.drawio b/KsatSupplymentLibrary/flow.drawio new file mode 100644 index 0000000..2616b23 --- /dev/null +++ b/KsatSupplymentLibrary/flow.drawio @@ -0,0 +1 @@ +5VzbcqM4EP0aHrOFkATiEdt4tmr2MjV52NmnLWIrNrtgORjH9nz9SkKYm5wh4wTZTtWUB1oIwVH3Uau7iQXH6f5TFq2Xv7M5TSzHnu8tOLEcB2AM+H9CclASUEoWWTxXskpwH3+nSmgr6Tae003jwpyxJI/XTeGMrVZ0ljdkUZaxXfOyR5Y0R11HC9oR3M+ipCv9K57ny0JKHK+S/0rjxbIcGbh+0ZJG5cXqTTbLaM52NREMLTjOGMuLo3Q/polAr8Sl6Dc90Xp8sIyu8j4d9p8/fU3/+YxX0bf7pzD6cvc13NzB4i7PUbJVL6weNj+UCNA5B0SdsixfsgVbRUlYSUcZ267mVAxj87Pqmt8YW3Mh4MJ/aZ4f1OxG25xx0TJPE9VajCkGOvluSrRh22xGX3ihUkeibEHzF65zjjPAdZeylObZgffLaBLl8XPzOSKlQ4vjdRXM/EAh/QrUQRf10LVIaAVYHPjIGrlWyH9H4l+ILRJYAejMTIW7AHG3jHN6v44kPDtujjqMn2mW0/3LKHdRUR0colS5NGakzneVZYBS3Zc1q3DtdwISapC8bv11euovMqm/jlZ/R15NW22pv0Qci4NxKblsjT6eG9No99YUGvVUaGxSoaFGoz8G7J5J2JGWR3xiBVPBEb5tBa44EMzCmyS/ENnEf31Xkg5fN4kVTgXF+NMuoSxZ+rDdDEIm0G6SCdSQCdFwCXkvLsEaeDkFc+gmAsNgIqAWYBJrZKeTKI+MEzJCLQx904QMb85F9npSg2+SGjy97rYcCl9osD9VSuzzTm6UCq1c8BcbgdIgL4QQkEaZByUEouXbtt+GBf2Oxpsdh+TS+ADbpvnA12BIJKmOdPp4YQ6u65nGD2oW/evm0zJU9UNCBSfmaqCgg90BfrtOWDTnsqct5TLTyur6FxdfuLntGOgbIINmN2Sa9f+DAA+gUZbQxSavZQfmgVY4xzXscIHb4w/YV42NRiihxtX9IMAXb2qMPzTbZcEfE8uHkjZ8i0w0kWAR9+GX2c0dHL8BuihGMR7TAfja9bhvZPJsb1l2DbIsOtQuWLN4lW9qd/4iBNWE++0Jt+3WnBV3rGbw+GhnTKouEOqJAB03F2E9oUUwsNNN1xYGdtGJ14LHeHwOdD3FVP5no7uVcbzaWxpkPMGEutvAa2cU0pNRoNGIJtBF3+Q6SMIi+F4EOINJzb2+uIwpbgeUjBMA6noI16W/Tt/40dme3U+tiKhF+S4YYEV0dCzlJsInfGTy6WYsYZlscZ+2TDqLDvRo5FK7LnILP7JIGah0lwzOlqYnw9xHg1Nj8Gcuhim7y90tGZftD1njzuI+lQcrSnkmVhDKlTuQfm/NsGVsXQ7oiVaNJ1yMRdRDBUEp8Y0bP2olNHzj0XjYzfBcmfH3LlgzYvzAdvVTPu3bYRi6OBG14lZTJLQ8i4x0q6md3t0ZNyvSMiti3KwcI7tMDld2+Cb6/wIJLAV/S4HN/XwlmOzVEMXZoX72hWYxh4BmSviWlur0tNTC0TPlZpaP2dgPNYIqHJfLCtNiTVJy0KAK1FXK+II7CvpQS7XciIv12JO1ul0Q+VDxekOHccRhE0THeGYXdTXvyhdn6Pc0eWQ0s4tuLsvQG/hTRjJQlkFXDOKKug9ttbNy6GvpM5Ms7La8Ds90dRK6uUo71Nu5t/VTNRB/XHtOoTfOZyclf2oT5baK2Hzy8h7Khy9e/z5bKKTbQrki66+yczIC8dpohwpjygI5oimHM8h3xDTf4ZuLxKO+pcXI6BYJnSgubq3WsthF6LMrCuZ1pS0DxwkAaMVWzBfIYQ1rXLkO980mIaPZJKSv5RZVx7bSYVGHfAlVWQC0v7Izvd9HOr+9myE4XdZ9zAfUv1ISTX6t1+kV8iwieYyTZHxMfsBHMqOzGZdv8oz9R2stDwQjbL/RHLa/ZTD/pSS+uRIv3LfECxutrcPdfVqZRAuQRZBYOblRkO72dsj4GHBaiyXSFINqNfb9HL6bK2rGvb/uNVpNjnX1VeWeRBB/wLVV6m3AVVfGfvnvuR6fGaJ2Wul6bLxAA2uI4Lq0HA/FyydyqqhVRVbmVI/3KJ5Mdaum69XZ3nath4d/kO3tFIc4A4Qq8Ks+bH43R+xNrLXlGnuOaWt1NVEJzUf5RPwSUH2LazqneGnRbLe7M/7jzw5E/IXzJhZREi9W/HjGX1yksUcClngWJYFqSOP5vKBIuom/Rw/yVoIklXXz++KRhSfiXpwVNwVBgs7Cs2Ir+jbYwzJ/WpKApn4BarB3Xo89P63+YlbBJ9UfHoPh/w== \ No newline at end of file diff --git a/KsatSupplymentLibrary/packages.config b/KsatSupplymentLibrary/packages.config new file mode 100644 index 0000000..b82eda8 --- /dev/null +++ b/KsatSupplymentLibrary/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/S3Demo.sln b/S3Demo.sln index 0bbe9bd..97d3ebd 100644 --- a/S3Demo.sln +++ b/S3Demo.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.31702.278 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "S3Demo", "S3Demo\S3Demo.csproj", "{10785A7F-B71E-4576-BD28-3979CD9A005C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KsatSupplymentLibrary", "KsatSupplymentLibrary\KsatSupplymentLibrary.csproj", "{3C90349C-2148-4D79-9881-7B3474EA8AF7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {10785A7F-B71E-4576-BD28-3979CD9A005C}.Debug|Any CPU.Build.0 = Debug|Any CPU {10785A7F-B71E-4576-BD28-3979CD9A005C}.Release|Any CPU.ActiveCfg = Release|Any CPU {10785A7F-B71E-4576-BD28-3979CD9A005C}.Release|Any CPU.Build.0 = Release|Any CPU + {3C90349C-2148-4D79-9881-7B3474EA8AF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3C90349C-2148-4D79-9881-7B3474EA8AF7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3C90349C-2148-4D79-9881-7B3474EA8AF7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3C90349C-2148-4D79-9881-7B3474EA8AF7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/S3Demo/App.config b/S3Demo/App.config index 8e15646..d8c2c6c 100644 --- a/S3Demo/App.config +++ b/S3Demo/App.config @@ -1,6 +1,25 @@ - + - - - + + +
+ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/S3Demo/Run.cs b/S3Demo/Run.cs index 0d20f3f..fe3a130 100644 --- a/S3Demo/Run.cs +++ b/S3Demo/Run.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using System.Diagnostics; using System.Text.RegularExpressions; using System.IO; +using Ksat.Supplyment.Library.Model; namespace S3Demo { @@ -45,8 +46,27 @@ namespace S3Demo private static string[] paths = { @"D:\ClientDir" }; private static string suffix = "*.png"; private static bool incsubdir = true; + public static void Main() { + /// 写入数据库操作 + //using (var dev = new CodeFirstDbContext()) + //{ + // dev.UploadCaches.Add(new Ksat.Supplyment.Library.Model.Uploader.UploadCache() { + // Id = 1, + // UploaderID = "02", + // CreateAt = DateTime.Now.AddHours(-1), + // RetryAt = DateTime.Now, + // RetryCount = 1, + // ErrorInfo = "null", + // RequestData = "testInfo" + // }); + // var i = dev.SaveChanges(); + // Console.WriteLine(i); + //} + + + try { //FileModel.onFileChange(paths, suffix, true); @@ -70,7 +90,7 @@ namespace S3Demo watch.EnableRaisingEvents = true; } - #region S3相关测试 + #region S3相关测试 /* //creating Bucket //await CreateBucket.CreatingBucket("minio/bu29", credentials, conf); @@ -116,9 +136,9 @@ namespace S3Demo //await new AmazonS3Client(credentials, conf).DeleteBucketAsync(bucketName); //Console.WriteLine("delete bucket " + bucketName); */ - #endregion + #endregion - #region 路径解析 + #region 路径解析 //string fullpath = @"C:\line01\AOI\20211129\120955851P107CN14T00001OK.png"; //string fileName = System.IO.Path.GetFileNameWithoutExtension(fullpath); //string date = System.IO.Path.GetDirectoryName(fullpath).Split('\\')[3]; @@ -137,7 +157,7 @@ namespace S3Demo //Console.WriteLine("datetime: " + datetime); //string dt = DateTime.ParseExact(datetime, "yyyyMMddHHmmssfff", System.Globalization.CultureInfo.CurrentCulture).ToString("yyyy-MM-dd HH:mm:ss:fff"); //Console.WriteLine("format: " + dt); - #endregion + #endregion } catch (Exception ex) { diff --git a/S3Demo/S3Demo.csproj b/S3Demo/S3Demo.csproj index e201e7e..3175730 100644 --- a/S3Demo/S3Demo.csproj +++ b/S3Demo/S3Demo.csproj @@ -1,5 +1,6 @@  + Debug @@ -11,6 +12,8 @@ v4.5 512 true + + preview @@ -41,8 +44,27 @@ ..\packages\AWSSDK.S3.3.7.5\lib\net45\AWSSDK.S3.dll + + ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.dll + + + ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.SqlServer.dll + + + ..\packages\SQLite.CodeFirst.1.7.0.34\lib\net45\SQLite.CodeFirst.dll + + + + ..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.115.5\lib\net45\System.Data.SQLite.dll + + + ..\packages\System.Data.SQLite.EF6.1.0.115.5\lib\net45\System.Data.SQLite.EF6.dll + + + ..\packages\System.Data.SQLite.Linq.1.0.115.5\lib\net45\System.Data.SQLite.Linq.dll + @@ -67,5 +89,24 @@ + + + {3c90349c-2148-4d79-9881-7b3474ea8af7} + KsatSupplymentLibrary + + + + + + + + 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + + + + + + + \ No newline at end of file diff --git a/S3Demo/packages.config b/S3Demo/packages.config index 825e538..1bb408c 100644 --- a/S3Demo/packages.config +++ b/S3Demo/packages.config @@ -2,4 +2,11 @@ + + + + + + + \ No newline at end of file