Net5 WorkService 继承 Quarzt 以及 Net5处理文件上传

  • A+
所属分类:.NET技术
摘要

Net5 版本以Core为底层非framework框架的windowservice 服务。      

Net5 版本以Core为底层非framework框架的windowservice 服务。

Net5 WorkService 继承 Quarzt 以及 Net5处理文件上传

 

 

 

Net5 WorkService 继承 Quarzt 以及 Net5处理文件上传

 

 

Net5 WorkService 继承 Quarzt 以及 Net5处理文件上传

 

在VS里叫WorkService 可以以CMD方式运行也可以以Windowservice方式运行,部署简单。

Net5 WorkService 继承 Quarzt 以及 Net5处理文件上传

 

 

 

Program.cs如下,是关键配置和启动项

using Microsoft.Extensions.Hosting; using Quartz; using WorkerService.Common; using WorkerService.Job;  namespace WorkerService {     public class Program     {         public static void Main(string[] args)         {                          CreateHostBuilder(args).Build().Run();         }                public static IHostBuilder CreateHostBuilder(string[] args) =>             Host.CreateDefaultBuilder(args).UseWindowsService()                 .ConfigureServices((hostContext, services) =>                 {                      #region  原生work Service                      //自定义调度                      //services.AddHostedService<Worker>();                      #endregion                        #region quartz 原始版本                      //这个版本    trigger  job Schedule 是唯一关联,不能一个组下多个任务                       //services.AddQuartz(q =>                     //{                     //    q.UseMicrosoftDependencyInjectionScopedJobFactory();                      //    // Create a "key" for the job                     //    var jobKey = new JobKey("HelloTestJob");                      //    // Register the job with the DI container                     //    q.AddJob<HelloTestJob>(opts => opts.WithIdentity(jobKey));                      //    // Create a trigger for the job                     //    q.AddTrigger(opts => opts                     //        .ForJob(jobKey) // link to the HelloWorldJob                     //        .WithIdentity("HelloTestJob-trigger") // give the trigger a unique name                     //        .WithCronSchedule("0/1 * * * * ?")); // run every 1 seconds                      //});                      //services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);                       #endregion                        #region quarzt 优化版本                       //services.AddQuartz(q =>                     //{                     //    q.UseMicrosoftDependencyInjectionScopedJobFactory();                      //    // Register the job, loading the schedule from configuration                     //    q.AddJobAndTrigger<HelloTestJob>(hostContext.Configuration, "0/1 * * * * ?");//每秒运行一次                      //    q.AddJobAndTrigger<HelloTestJob2>(hostContext.Configuration, "0/1 * * * * ?");                     //});                      //services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);                       #endregion                        #region  温湿度 SF6 红外图片上传                                     services.AddQuartz(q =>                     {                         q.UseMicrosoftDependencyInjectionScopedJobFactory();                          //每秒 0/1 * * * * ?   每小时  0 0 * * * ?                         // Register the job, loading the schedule from configuration                         q.AddJobAndTrigger<TemperatureJob>(hostContext.Configuration, "0 0 * * * ?");                          q.AddJobAndTrigger<SF6Job>(hostContext.Configuration, "0 0 * * * ?");                          q.AddJobAndTrigger<InfraredJob>(hostContext.Configuration, "0 0 * * * ?");                     });                      services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);                        #endregion                    });     }                   }

原始的 Host.CreateDefaultBuilder(args) 需要增加  .UseWindowsService()  支持 对windowservice 

quarzt 在 NET5的nuget 中叫 Quartz.Extensions.Hosting

 

services.AddHostedService<Worker>();   是原始的windows定时任务版本 

代码如下, 在 await Task.Delay(1000, stoppingToken);  设定定时启动的毫秒数就可以了

using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using System; using System.IO; using System.Threading; using System.Threading.Tasks;  namespace WorkerService.Job.Test {     public class Worker : BackgroundService     {         private readonly ILogger<Worker> _logger;          public Worker(ILogger<Worker> logger)         {             _logger = logger;         }          protected override async Task ExecuteAsync(CancellationToken stoppingToken)         {             while (!stoppingToken.IsCancellationRequested)             {                 _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);                   FileStream stream = new FileStream(@"d:aa.txt", FileMode.Create);//fileMode指定是读取还是写入                 StreamWriter writer = new StreamWriter(stream);                 writer.WriteLine("123456"+ DateTimeOffset.Now);//写入一行,写完后会自动换行                 writer.Write("abc");//写完后不会换行                 writer.WriteLine("ABC");                 writer.Close();//释放内存                 stream.Close();//释放内存                   await Task.Delay(1000, stoppingToken);             }         }     } }

quartz 原始版本(program.cs代码截图)

Net5 WorkService 继承 Quarzt 以及 Net5处理文件上传

 

 

 在目前这个quartz 3.3.3 版本中好像不能一个Key 下多个Job集成作业。所以每个job需要一个一个注册。推荐使用优化版本

 

 quarzt 优化版本(program.cs代码截图)

对原始版本进行了封装。在每一次调用的时候会注册新的唯一实例。

Net5 WorkService 继承 Quarzt 以及 Net5处理文件上传

 

 

以下是帮助类

using Microsoft.Extensions.Configuration; using Quartz; using System;  namespace WorkerService.Common {     public static class ServiceCollectionQuartzConfiguratorExtensions     {         public static void AddJobAndTrigger<T>(             this IServiceCollectionQuartzConfigurator quartz,             IConfiguration config, string cronSchedule)             where T : IJob         {             // Use the name of the IJob as the appsettings.json key             string jobName = typeof(T).Name;              // Try and load the schedule from configuration             var configKey = $"Quartz:{jobName}";             //var cronSchedule = config[configKey];              // Some minor validation             if (string.IsNullOrEmpty(cronSchedule))             {                 throw new Exception($"No Quartz.NET Cron schedule found for job in configuration at {configKey}");             }              // register the job as before             var jobKey = new JobKey(jobName);             quartz.AddJob<T>(opts => opts.WithIdentity(jobKey));              quartz.AddTrigger(opts => opts                 .ForJob(jobKey)                 .WithIdentity(jobName + "-trigger")                 .WithCronSchedule(cronSchedule)); // use the schedule from configuration         }     } }

以下是Job

using Microsoft.Extensions.Logging; using Quartz; using System; using System.IO; using System.Threading.Tasks;  namespace WorkerService.Job.Test {      [DisallowConcurrentExecution]     public class HelloTestJob2 : IJob     {         private readonly ILogger<HelloTestJob2> _logger;           public HelloTestJob2(ILogger<HelloTestJob2> logger)         {             _logger = logger;          }          public Task Execute(IJobExecutionContext context)         {             FileStream stream = new FileStream(@"d:aa1.txt", FileMode.Create);//fileMode指定是读取还是写入             StreamWriter writer = new StreamWriter(stream);             writer.WriteLine("123456aaa" + DateTimeOffset.Now);//写入一行,写完后会自动换行             writer.Write("abc");//写完后不会换行             writer.WriteLine("ABC");             writer.Close();//释放内存             stream.Close();//释放内存              return Task.CompletedTask;         }     }    }

程序会根据Corn 设定的运行时间定期在 Task Execute(IJobExecutionContext context)方法内运行

 

 

然后就是蛮搞笑的,大伙都不用Net5 吗。写服务上传文件。遇到问题搜索NET5处理文件上传问题,居然都是空白的。 那我就只好自己写解决方案了。

 

 

客户端图片上传的HTTPHelper.cs部分代码如下

       /// <summary>         /// 上传文件         /// </summary>         /// <param name="url">请求地址</param>         /// <param name="path">文件路径(带文件名)</param>         /// <returns></returns>         public static string HttpPostFile(string url, string path)         {             // 设置参数             HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;             CookieContainer cookieContainer = new CookieContainer();             request.CookieContainer = cookieContainer;             request.AllowAutoRedirect = true;             request.Method = "POST";string boundary = DateTime.Now.Ticks.ToString("X"); // 随机分隔线             request.ContentType = "multipart/form-data;charset=utf-8;boundary=" + boundary;             byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes("rn--" + boundary + "rn");             byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("rn--" + boundary + "--rn");              int pos = path.LastIndexOf("\");             string fileName = path.Substring(pos + 1);              //请求头部信息             StringBuilder sbHeader = new StringBuilder(string.Format("Content-Disposition:form-data;name="file";filename="{0}"rnContent-Type:application/octet-streamrnrn", fileName));             byte[] postHeaderBytes = Encoding.UTF8.GetBytes(sbHeader.ToString());              StringBuilder builder = new StringBuilder($"Content-Disposition:form-data;name="subPath"rnrntmswechat");             byte[] postHeaderBytestwo = Encoding.UTF8.GetBytes(builder.ToString());              FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);             byte[] bArr = new byte[fs.Length];             fs.Read(bArr, 0, bArr.Length);             fs.Close();              Stream postStream = request.GetRequestStream();             postStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);             postStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);             postStream.Write(bArr, 0, bArr.Length);             postStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);             postStream.Write(postHeaderBytestwo, 0, postHeaderBytestwo.Length);             postStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);             postStream.Close();              //发送请求并获取相应回应数据             HttpWebResponse response = request.GetResponse() as HttpWebResponse;             //直到request.GetResponse()程序才开始向目标网页发送Post请求             Stream instream = response.GetResponseStream();             StreamReader sr = new StreamReader(instream, Encoding.UTF8);             //返回结果网页(html)代码             string content = sr.ReadToEnd();             return content;         }

重点是服务端的接收,部分代码如下

try                     {                     var files = Request.Form.Files;                     if (files != null)                     {                         var file = files[0];                                          var location = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + $"Image\" + file.FileName;                          if (!Directory.Exists(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + $"Image\")) //判断上传文件夹是否存在,若不存在,则创建                         {                             Directory.CreateDirectory(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + $"Image\"); //创建文件夹                         }                          using (var stream = new FileStream(location, FileMode.Create))                         {                             await file.CopyToAsync(stream);                             result = 1;                         }                     }                      //using (var reader = new StreamReader(Request.Body))//从身体里读取                     //{                      //    var body = await reader.ReadToEndAsync();                                             //}                     }                     catch (Exception e )                     {                          throw;                     }

 哪怕你用的是文件流上传,不是表单提交。但是你的文件依旧在Request.Form.Files 里!!!! 

 

但你也可以通过Request.body 读到流

//using (var reader = new StreamReader(Request.Body))//从身体里读取 //{  // var body = await reader.ReadToEndAsync();  //}