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


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

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

    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代码截图)

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

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

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

    以下是帮助类

    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("\r\n--" + boundary + "\r\n");
                byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
    
                int pos = path.LastIndexOf("\\");
                string fileName = path.Substring(pos + 1);
    
                //请求头部信息
                StringBuilder sbHeader = new StringBuilder(string.Format("Content-Disposition:form-data;name=\"file\";filename=\"{0}\"\r\nContent-Type:application/octet-stream\r\n\r\n", fileName));
                byte[] postHeaderBytes = Encoding.UTF8.GetBytes(sbHeader.ToString());
    
                StringBuilder builder = new StringBuilder($"Content-Disposition:form-data;name=\"subPath\"\r\n\r\ntmswechat");
                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();
    
    //}
  • 相关阅读:
    Java hutool/java 常用方法
    版本控制工具 TortoiseGit 基本配置
    SpringBlade 码云上我自己的fork的仓库简单使用
    版本控制工具 Git SourceTree SSH 连接码云
    版本控制工具 Git SourceTree 报错 fatal: could not read Username for 'https://gitee.com': No such file or directory
    在充电桩联网部署方案中4G DTU的优势是什么
    4G DTU模块和串口设备连接的方式
    4g物联网模块的原理
    4G DTU采用的4G通信模块介绍
    4G DTU数据传输终端的功能介绍
  • 原文地址:https://www.cnblogs.com/Gao1234/p/15905510.html
Copyright © 2020-2023  润新知