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(); //}

Net5 WorkService 继承 Quarzt 以及 Net5处理文件上传的更多相关文章

  1. Spring Mvc 笔记二之异常和文件上传

    spring mvc的异常与文件上传 1.异常: spring注解版的异常有局部异常和全局异常                1.局部异常对单个controller有效;(在controller类写一 ...

  2. Blazor组件自做九: 用20行代码实现文件上传,浏览目录功能 (3)

    接上篇 Blazor组件自做九: 用20行代码实现文件上传,浏览目录功能 (2) 7. 使用配置文件指定监听地址 打开 appsettings.json 文件,加入一行 "UseUrls&q ...

  3. ASP.NET MVC5+EF6+EasyUI 后台管理系统(32)-swfupload多文件上传[附源码]

    系列目录 文件上传这东西说到底有时候很痛,原来的asp.net服务器控件提供了很简单的上传,但是有回传,还没有进度条提示.这次我们演示利用swfupload多文件上传,项目上文件上传是比不可少的,大家 ...

  4. Struts2入门(七)——Struts2的文件上传和下载

    一.前言 在之前的随笔之中,我们已经了解Java通过上传组件来实现上传和下载,这次我们来了解Struts2的上传和下载. 注意:文件上传时,我们需要将表单提交方式设置为"POST" ...

  5. THINKPHP源码学习--------文件上传类

    TP图片上传类的理解 在做自己项目上传图片的时候一直都有用到TP的上传图片类,所以要进入源码探索一下. 文件目录:./THinkPHP/Library/Think/Upload.class.php n ...

  6. 【原创】JEECMS v6~v7任意文件上传漏洞(2)

    文章作者:rebeyond 受影响版本:v6~v7 漏洞说明: JEECMS是国内Java版开源网站内容管理系统(java cms.jsp cms)的简称.该系统基于java技术开发,继承其强大.稳定 ...

  7. 【原创】JEECMS v6~v7任意文件上传漏洞(1)

    文章作者:rebeyond 受影响版本:v6~v7 漏洞说明: JEECMS是国内Java版开源网站内容管理系统(java cms.jsp cms)的简称.该系统基于java技术开发,继承其强大.稳定 ...

  8. 【C#公共帮助类】FTPClientHelper帮助类,实现文件上传,目录操作,下载等动作

    关于本文档的说明 本文档使用Socket通信方式来实现ftp文件的上传下载等命令的执行 欢迎传播分享,必须保持原作者的信息,但禁止将该文档直接用于商业盈利. 本人自从几年前走上编程之路,一直致力于收集 ...

  9. 【Java EE 学习 35 下】【struts2】【struts2文件上传】【struts2自定义拦截器】【struts2手动验证】

    一.struts2文件上传 1.上传文件的时候要求必须使得表单的enctype属性设置为multipart/form-data,把它的method属性设置为post 2.上传单个文件的时候需要在Act ...

  10. 几款极好的 JavaScript 文件上传插件

    文件上传功能作为网页重要的组成部分,几乎无处不在,从简单的单个文件上传到复杂的批量上传.拖放上传,需要开发者花费大量的时间和精力去处理,以期实现好用的上传功能.这篇文章向大家推荐几款很棒的 JavaS ...

随机推荐

  1. java基础(13)--静态变量、静态代码块、实例代码块

    一.静态变量/静态代码块特点: 1.类加载时执行静态代码块,并初始化静态变量 2.先于main()执行 3.只加载一次 4.可访问静态变量,不可访问实例变量   二.实例语句块: 1.需要实例化,对象 ...

  2. Kubernetes 疑难杂症汇总

    1. 部署报错:The requested fsGroup is 123, but the volume local-pv-c7ef339e has GID 1000710000. The volum ...

  3. Go image registry

    0. 前言 OpenShift image registry 概述 介绍了 OpenShift 平台上 registry 的基本结构.进一步地,本文将介绍在 Kubernetes 平台上,如何使用 G ...

  4. docker 镜像管理之 overlay2 最佳实践

    1. Docker 镜像 Docker 镜像是个只读的容器模板,它组成了 Docker 容器的静态文件系统运行环境 rootfs,是启动 Docker 容器的基础. Docker 镜像是容器的静态视角 ...

  5. wireshark 显示过滤表达式

    转载请注明出处: 1.根据协议过滤: 在显示过滤表达式的输入框中直接输入对应的协议类型即可:http   tcp  udp 2.根据 IP 过滤: 根据源IP地址过滤:如源地址IP为:127.0.0. ...

  6. 存储器(Memory)

    存储器(Memory) 通信领域中有很多重要的部分,比如基带.射频芯片,存储器. 1.存储器是什么?和内存如何进行区分? 作为数据的载体,存储器是任何电子设备中都必不可少的单元.由于存储器之间相似的名 ...

  7. Python Code_06基础篇

    条件表达式 # coding:utf-8 # author : 写bug的盼盼 # development time : 2021/8/28 7:38 num_a = input('请输入第一个整数' ...

  8. 海思Hi35xx 实现本地和远程升级程序的方法

    前言 嵌入式linux设备要进行软件升级有很种多方式方法,总的来说可以分为本地升级和远程升级. 本地升级包括升级工具升级,存储介质升级等,远程升级是指通过网络进行程序升级. 这里介绍一种同时至此本地和 ...

  9. [转帖]解Bug之路-记一次JVM堆外内存泄露Bug的查找

    https://zhuanlan.zhihu.com/p/245401095 解Bug之路-记一次JVM堆外内存泄露Bug的查找 前言 JVM的堆外内存泄露的定位一直是个比较棘手的问题.此次的Bug查 ...

  10. [转帖]“炫技” 还是 “真硬核”,OpenPPL 实测阿里「倚天 710」芯片

    https://my.oschina.net/openppl/blog/5524424   本文将以深度学习模型推理应用为出发点,对「倚天 710」这款 ARM Server 芯片进行性能方面的实测. ...