public ActionResult GetShortUrl(string codesStr) { var codes = GetCodes(codesStr); ConcurrentDictionary <int, string> dic = new ConcurrentDictionary <int, string>(); List <Task> tasks = new List <Task>(); List <Exception> exceptions = new List <Exception>(); var totalCount = codes.Length; var successCount = 0; var finishedCount = 0; for (int i = 0; i < totalCount; i++) { var index = i; try { var task = Senparc.Weixin.MP.AdvancedAPIs.UrlApi.ShortUrlAsync(Config.SenparcWeixinSetting.MpSetting.WeixinAppId, "long2short", codes[index]) .ContinueWith(weixinResult => { dic[index] = weixinResult.Result.short_url; successCount++; }) .ConfigureAwait(false); } catch (Exception ex) { exceptions.Add(ex); dic[index] = ""; } finally { finishedCount++; } //tasks.Add(task); } //Task.WaitAll(tasks.ToArray(), TimeSpan.FromMinutes(1)); var dt1 = SystemTime.Now; while (successCount < codes.Length && SystemTime.NowDiff(dt1).TotalSeconds < 60) { Thread.Sleep(1000); } var result = string.Join(Environment.NewLine, dic.OrderBy(z => z.Key).Select(z => z.Value)); return(Json(new { result = result, totalCount = totalCount, successCount = successCount, errors = string.Join(" , ", exceptions.Select(z => z.Message).ToArray()) })); }
public IApplicationBuilder UseMiddleware(IApplicationBuilder app) { var docDir = Path.Combine(Senparc.Ncf.Core.Config.SiteConfig.WebRootPath, "NcfDocs\\cn\\docs\\doc\\"); var assetsDir = Path.GetFullPath(Path.Combine(docDir, "..\\", "assets")); app.Map("/Docs", async builder => { var indexHtmlFileDir = Path.Combine(Senparc.Ncf.Core.Config.SiteConfig.WebRootPath, "NcfDocs\\cn\\docs\\assets\\"); var indexHtmlFilePath = Path.Combine(indexHtmlFileDir, "index.html"); if (!File.Exists(indexHtmlFilePath)) { using (var scope = app.ApplicationServices.CreateScope()) { UpdateDocs updateDocs = new UpdateDocs(scope.ServiceProvider); updateDocs.Run(new UpdateDocs_Parameters()); //等待更新 var dt1 = SystemTime.Now; while (SystemTime.NowDiff(dt1) < TimeSpan.FromSeconds(10)) { if (File.Exists(indexHtmlFilePath)) { break; } await Task.Delay(1000); } } } builder.Use(async(context, next) => { context.Response.ContentType = "text/html; charset=utf-8"; using (var fs = new FileStream(indexHtmlFilePath, FileMode.Open)) { await fs.CopyToAsync(context.Response.Body).ConfigureAwait(false); } }); }); app.UseStaticFiles(new StaticFileOptions() { FileProvider = new PhysicalFileProvider(assetsDir), RequestPath = new PathString("") }); return(app); }
public async Task <IActionResult> PostFile(string byStream = null) { var dt1 = SystemTime.Now; var filePath = Path.GetFullPath("App_Data/cover.png");//也可以上传其他任意文件 var fileDictionary = new Dictionary <string, string>(); if (byStream != null) { //使用Stream传入,而不是文件名 SenparcTrace.SendCustomLog("Post 文件信息", $"使用文件流放入 fileDictionary 中,并将修改文件名。"); using (var fs = System.IO.File.OpenRead(filePath)) { var formFileData = new FormFileData(Path.GetFileName(filePath), fs); formFileData.FileName = $"changed-{formFileData.FileName}";//修改文件名 fileDictionary["image"] = formFileData.GetFileValue(); } } else { SenparcTrace.SendCustomLog("Post 文件信息", $"使用文件物理地址放入 fileDictionary 中,保留原文件名。"); fileDictionary["image"] = filePath; } var url = "https://*****:*****@"<html> <head> <meta http-equiv=Content-Type content=""text/html;charset=utf-8""> <title>CO2NET 文件 Post 测试 - {note}</title> </head> <body> <p>如果在下方看到《微信开发深度解析》图书封面,表示测试成功({note})。可通过 SenparcTrace 日志查看更多过调试信息日志。</p> <p>耗时:{timeCost.TotalMilliseconds} ms,平均:{averageCost} ms</p> <img src=""data:image/png; base64,{result}"" /> </body> </html>"; return(Content(html, "text/html")); }
public void ThreadConfig(XncfThreadBuilder xncfThreadBuilder) { xncfThreadBuilder.AddThreadInfo(new Ncf.XncfBase.Threads.ThreadInfo( name: "定时备份", intervalTime: TimeSpan.FromSeconds(30), task: async(app, threadInfo) => { try { //SenparcTrace.SendCustomLog("执行调试", "DatabaseToolkit.Register.ThreadConfig"); threadInfo.RecordStory("开始检测并备份"); using (var scope = app.ApplicationServices.CreateScope()) { var serviceProvider = scope.ServiceProvider; //检测当前模块是否可用 XncfRegisterManager xncfRegisterManager = new XncfRegisterManager(serviceProvider); var xncfIsValiable = await xncfRegisterManager.CheckXncfValiable(this); if (!xncfIsValiable) { throw new NcfModuleException($"{this.MenuName} 模块当前不可用,跳过数据库自动备份轮询"); } //初始化数据库备份方法 BackupDatabase backupDatabase = new BackupDatabase(serviceProvider); //初始化参数 var backupParam = new BackupDatabase.BackupDatabase_Parameters(); var dbConfigService = serviceProvider.GetService <ServiceBase <DbConfig> >(); var dbConfig = await dbConfigService.GetObjectAsync(z => true); var stopBackup = false; try { if (dbConfig != null && dbConfig.BackupCycleMinutes > 0 && !dbConfig.BackupPath.IsNullOrEmpty()) { if (SystemTime.NowDiff(dbConfig.LastBackupTime) > TimeSpan.FromMinutes(dbConfig.BackupCycleMinutes)) { backupParam.Path = dbConfig.BackupPath; //await backupParam.LoadData(serviceProvider); //threadInfo.RecordStory("完成备份设置数据载入"); } else { stopBackup = true; } } else { threadInfo.RecordStory("不需要备份,或没有设置备份周期/路径,已忽略本次备份计划"); stopBackup = true; //不需要备份,或没有设置,返回 } } catch (Exception ex) { threadInfo.RecordStory($@"遇到异常,可能未配置数据库,已忽略本次备份计划。如需启动,请更新此模块到最新版本。 异常信息:{ex.Message} {ex.StackTrace}"); stopBackup = true; //可能没有配置数据库,返回 } if (stopBackup) { return; } //执行备份方法 threadInfo.RecordStory("备份开始:" + backupParam.Path); var result = backupDatabase.Run(backupParam); if (!result.Success) { threadInfo.RecordStory("执行备份发生异常:" + result.Message); throw new Exception("执行备份发生异常"); } dbConfig.RecordBackupTime(); await dbConfigService.SaveObjectAsync(dbConfig); threadInfo.RecordStory("完成数据库自动备份:" + result.Message); SenparcTrace.SendCustomLog("完成数据库自动备份", backupParam.Path); } } catch (NcfModuleException ex) { throw; } catch { throw; } finally { threadInfo.RecordStory("检测并备份结束"); } }, exceptionHandler: ex => { SenparcTrace.SendCustomLog("DatabaseToolkit", $@"{ex.Message} {ex.StackTrace} {ex.InnerException?.StackTrace}"); return(Task.CompletedTask); })); }
public void ConvertTest() { var jsonStr = @"{ ""UserName"": ""FromUserName(OpenId)"", ""LastActiveTime"": ""2019-09-24T15:17:54.3197922+00:00"", ""ThisActiveTime"": ""2019-09-23T07:17:59.6691421+00:00"", ""RequestMessages"": [ { ""MsgType"": 0, ""Content"": ""天气"", ""bizmsgmenuid"": """", ""MsgId"": 637047906563632900, ""Encrypt"": """", ""ToUserName"": ""ToUserName"", ""FromUserName"": ""FromUserName(OpenId)"", ""CreateTime"": ""2019-09-22T23:14:06+08:00"" }, { ""MsgType"": 0, ""Content"": ""天气"", ""bizmsgmenuid"": """", ""MsgId"": 637047906563642900, ""Encrypt"": """", ""ToUserName"": ""ToUserName"", ""FromUserName"": ""FromUserName(OpenId)"", ""CreateTime"": ""2019-09-22T23:14:08+08:00"" }, { ""MsgType"": 0, ""Content"": ""天气"", ""bizmsgmenuid"": """", ""MsgId"": 637047906563652900, ""Encrypt"": """", ""ToUserName"": ""ToUserName"", ""FromUserName"": ""FromUserName(OpenId)"", ""CreateTime"": ""2019-09-22T23:14:08+08:00"" }, { ""MsgType"": 0, ""Content"": ""天气"", ""bizmsgmenuid"": """", ""MsgId"": 637047906563662800, ""Encrypt"": """", ""ToUserName"": ""ToUserName"", ""FromUserName"": ""FromUserName(OpenId)"", ""CreateTime"": ""2019-09-22T23:14:08+08:00"" }, { ""MsgType"": 0, ""Content"": ""天气"", ""bizmsgmenuid"": """", ""MsgId"": 637047906563672800, ""Encrypt"": """", ""ToUserName"": ""ToUserName"", ""FromUserName"": ""FromUserName(OpenId)"", ""CreateTime"": ""2019-09-22T23:14:08+08:00"" }, { ""MsgType"": 0, ""Content"": ""天气"", ""bizmsgmenuid"": """", ""MsgId"": 637047906563682800, ""Encrypt"": """", ""ToUserName"": ""ToUserName"", ""FromUserName"": ""FromUserName(OpenId)"", ""CreateTime"": ""2019-09-22T23:14:10+08:00"" }, { ""MsgType"": 0, ""Content"": ""1234"", ""bizmsgmenuid"": """", ""MsgId"": 637047910625007590, ""Encrypt"": """", ""ToUserName"": ""ToUserName"", ""FromUserName"": ""FromUserName(OpenId)"", ""CreateTime"": ""2019-09-22T23:17:49+08:00"" }, { ""MsgType"": 0, ""Content"": ""1234"", ""bizmsgmenuid"": """", ""MsgId"": 637047910625017600, ""Encrypt"": """", ""ToUserName"": ""ToUserName"", ""FromUserName"": ""FromUserName(OpenId)"", ""CreateTime"": ""2019-09-22T23:17:53+08:00"" }, { ""MsgType"": 0, ""Content"": ""1234"", ""bizmsgmenuid"": """", ""MsgId"": 637047910625027600, ""Encrypt"": """", ""ToUserName"": ""ToUserName"", ""FromUserName"": ""FromUserName(OpenId)"", ""CreateTime"": ""2019-09-22T23:17:54+08:00"" }, { ""MsgType"": 0, ""Content"": ""天气"", ""bizmsgmenuid"": """", ""MsgId"": 637047910625037600, ""Encrypt"": """", ""ToUserName"": ""ToUserName"", ""FromUserName"": ""FromUserName(OpenId)"", ""CreateTime"": ""2019-09-22T23:17:59+08:00"" } ], ""ResponseMessages"": [ { ""MsgType"": 0, ""Content"": ""您刚才发送了文字信息:天气\r\n\r\n您刚才还发送了如下消息(10/0):\r\n23:13:22 【Text】天气\r\n23:13:21 【Text】天气\r\n23:13:20 【Text】天气\r\n23:11:13 【Text】天气\r\n23:11:05 【Text】12345\r\n23:08:32 【Text】苏州\r\n23:07:06 【Text】天气\r\n23:04:51 【Text】111222\r\n23:03:31 【Text】111222\r\n\r\n\r\n如果您在3分钟内连续发送消息,记录将被自动保留(当前设置:最多记录10条)。过期后记录将会自动清除。\r\n\r\n\r\n您还可以发送【位置】【图片】【语音】【视频】等类型的信息(注意是这几种类型,不是这几个文字),查看不同格式的回复。\r\nSDK官方地址:https://sdk.weixin.senparc.com\r\n"", ""ToUserName"": ""FromUserName(OpenId)"", ""FromUserName"": ""ToUserName"", ""CreateTime"": ""2019-09-22T23:13:24.8832361+08:00"" }, { ""MsgType"": 0, ""Content"": ""您刚才发送了文字信息:天气\r\n\r\n您刚才还发送了如下消息(10/0):\r\n23:13:24 【Text】天气\r\n23:13:22 【Text】天气\r\n23:13:21 【Text】天气\r\n23:13:20 【Text】天气\r\n23:11:13 【Text】天气\r\n23:11:05 【Text】12345\r\n23:08:32 【Text】苏州\r\n23:07:06 【Text】天气\r\n23:04:51 【Text】111222\r\n\r\n\r\n如果您在3分钟内连续发送消息,记录将被自动保留(当前设置:最多记录10条)。过期后记录将会自动清除。\r\n\r\n\r\n您还可以发送【位置】【图片】【语音】【视频】等类型的信息(注意是这几种类型,不是这几个文字),查看不同格式的回复。\r\nSDK官方地址:https://sdk.weixin.senparc.com\r\n"", ""ToUserName"": ""FromUserName(OpenId)"", ""FromUserName"": ""ToUserName"", ""CreateTime"": ""2019-09-22T23:14:06.8772982+08:00"" }, { ""MsgType"": 0, ""Content"": ""您刚才发送了文字信息:天气\r\n\r\n您刚才还发送了如下消息(10/0):\r\n23:14:06 【Text】天气\r\n23:13:24 【Text】天气\r\n23:13:22 【Text】天气\r\n23:13:21 【Text】天气\r\n23:13:20 【Text】天气\r\n23:11:13 【Text】天气\r\n23:11:05 【Text】12345\r\n23:08:32 【Text】苏州\r\n23:07:06 【Text】天气\r\n\r\n\r\n如果您在3分钟内连续发送消息,记录将被自动保留(当前设置:最多记录10条)。过期后记录将会自动清除。\r\n\r\n\r\n您还可以发送【位置】【图片】【语音】【视频】等类型的信息(注意是这几种类型,不是这几个文字),查看不同格式的回复。\r\nSDK官方地址:https://sdk.weixin.senparc.com\r\n"", ""ToUserName"": ""FromUserName(OpenId)"", ""FromUserName"": ""ToUserName"", ""CreateTime"": ""2019-09-22T23:14:08.1252882+08:00"" }, { ""MsgType"": 0, ""Content"": ""您刚才发送了文字信息:天气\r\n\r\n您刚才还发送了如下消息(10/0):\r\n23:14:08 【Text】天气\r\n23:14:06 【Text】天气\r\n23:13:24 【Text】天气\r\n23:13:22 【Text】天气\r\n23:13:21 【Text】天气\r\n23:13:20 【Text】天气\r\n23:11:13 【Text】天气\r\n23:11:05 【Text】12345\r\n23:08:32 【Text】苏州\r\n\r\n\r\n如果您在3分钟内连续发送消息,记录将被自动保留(当前设置:最多记录10条)。过期后记录将会自动清除。\r\n\r\n\r\n您还可以发送【位置】【图片】【语音】【视频】等类型的信息(注意是这几种类型,不是这几个文字),查看不同格式的回复。\r\nSDK官方地址:https://sdk.weixin.senparc.com\r\n"", ""ToUserName"": ""FromUserName(OpenId)"", ""FromUserName"": ""ToUserName"", ""CreateTime"": ""2019-09-22T23:14:08.7938944+08:00"" }, { ""MsgType"": 0, ""Content"": ""您刚才发送了文字信息:天气\r\n\r\n您刚才还发送了如下消息(10/0):\r\n23:14:08 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:06 【Text】天气\r\n23:13:24 【Text】天气\r\n23:13:22 【Text】天气\r\n23:13:21 【Text】天气\r\n23:13:20 【Text】天气\r\n23:11:13 【Text】天气\r\n23:11:05 【Text】12345\r\n\r\n\r\n如果您在3分钟内连续发送消息,记录将被自动保留(当前设置:最多记录10条)。过期后记录将会自动清除。\r\n\r\n\r\n您还可以发送【位置】【图片】【语音】【视频】等类型的信息(注意是这几种类型,不是这几个文字),查看不同格式的回复。\r\nSDK官方地址:https://sdk.weixin.senparc.com\r\n"", ""ToUserName"": ""FromUserName(OpenId)"", ""FromUserName"": ""ToUserName"", ""CreateTime"": ""2019-09-22T23:14:09.414496+08:00"" }, { ""MsgType"": 0, ""Content"": ""您刚才发送了文字信息:天气\r\n\r\n您刚才还发送了如下消息(10/1):\r\n23:14:08 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:06 【Text】天气\r\n23:13:24 【Text】天气\r\n23:13:22 【Text】天气\r\n23:13:21 【Text】天气\r\n23:13:20 【Text】天气\r\n23:11:13 【Text】天气\r\n\r\n\r\n如果您在3分钟内连续发送消息,记录将被自动保留(当前设置:最多记录10条)。过期后记录将会自动清除。\r\n\r\n\r\n您还可以发送【位置】【图片】【语音】【视频】等类型的信息(注意是这几种类型,不是这几个文字),查看不同格式的回复。\r\nSDK官方地址:https://sdk.weixin.senparc.com\r\n"", ""ToUserName"": ""FromUserName(OpenId)"", ""FromUserName"": ""ToUserName"", ""CreateTime"": ""2019-09-22T23:14:09.9626979+08:00"" }, { ""MsgType"": 0, ""Content"": ""您刚才发送了文字信息:天气\r\n\r\n您刚才还发送了如下消息(10/0):\r\n23:14:08 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:06 【Text】天气\r\n23:13:24 【Text】天气\r\n23:13:22 【Text】天气\r\n23:13:21 【Text】天气\r\n23:13:20 【Text】天气\r\n\r\n\r\n如果您在3分钟内连续发送消息,记录将被自动保留(当前设置:最多记录10条)。过期后记录将会自动清除。\r\n\r\n\r\n您还可以发送【位置】【图片】【语音】【视频】等类型的信息(注意是这几种类型,不是这几个文字),查看不同格式的回复。\r\nSDK官方地址:https://sdk.weixin.senparc.com\r\n"", ""ToUserName"": ""FromUserName(OpenId)"", ""FromUserName"": ""ToUserName"", ""CreateTime"": ""2019-09-22T23:14:10.2830586+08:00"" }, { ""MsgType"": 0, ""Content"": ""您刚才发送了文字信息:1234\r\n\r\n您刚才还发送了如下消息(10/0):\r\n23:14:10 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:06 【Text】天气\r\n23:13:24 【Text】天气\r\n23:13:22 【Text】天气\r\n23:13:21 【Text】天气\r\n\r\n\r\n如果您在3分钟内连续发送消息,记录将被自动保留(当前设置:最多记录10条)。过期后记录将会自动清除。\r\n\r\n\r\n您还可以发送【位置】【图片】【语音】【视频】等类型的信息(注意是这几种类型,不是这几个文字),查看不同格式的回复。\r\nSDK官方地址:https://sdk.weixin.senparc.com\r\n"", ""ToUserName"": ""FromUserName(OpenId)"", ""FromUserName"": ""ToUserName"", ""CreateTime"": ""2019-09-22T23:17:50.6362189+08:00"" }, { ""MsgType"": 0, ""Content"": ""您刚才发送了文字信息:1234\r\n\r\n您刚才还发送了如下消息(10/0):\r\n23:17:49 【Text】1234\r\n23:14:10 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:06 【Text】天气\r\n23:13:24 【Text】天气\r\n23:13:22 【Text】天气\r\n\r\n\r\n如果您在3分钟内连续发送消息,记录将被自动保留(当前设置:最多记录10条)。过期后记录将会自动清除。\r\n\r\n\r\n您还可以发送【位置】【图片】【语音】【视频】等类型的信息(注意是这几种类型,不是这几个文字),查看不同格式的回复。\r\nSDK官方地址:https://sdk.weixin.senparc.com\r\n"", ""ToUserName"": ""FromUserName(OpenId)"", ""FromUserName"": ""ToUserName"", ""CreateTime"": ""2019-09-22T23:17:53.8077989+08:00"" }, { ""MsgType"": 0, ""Content"": ""您刚才发送了文字信息:1234\r\n\r\n您刚才还发送了如下消息(10/0):\r\n23:17:53 【Text】1234\r\n23:17:49 【Text】1234\r\n23:14:10 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:08 【Text】天气\r\n23:14:06 【Text】天气\r\n23:13:24 【Text】天气\r\n\r\n\r\n如果您在3分钟内连续发送消息,记录将被自动保留(当前设置:最多记录10条)。过期后记录将会自动清除。\r\n\r\n\r\n您还可以发送【位置】【图片】【语音】【视频】等类型的信息(注意是这几种类型,不是这几个文字),查看不同格式的回复。\r\nSDK官方地址:https://sdk.weixin.senparc.com\r\n"", ""ToUserName"": ""FromUserName(OpenId)"", ""FromUserName"": ""ToUserName"", ""CreateTime"": ""2019-09-22T23:17:54.3355697+08:00"" } ], ""MaxRecordCount"": 10, ""StorageDataTypeName"": ""System.Int32"", ""StorageData"": 0, ""ExpireMinutes"": null, ""AppStoreState"": 2, ""CurrentAppDataItem"": { ""Name"": ""查天气"", ""Id"": ""3"", ""Note"": null, ""Version"": ""0.1.0"", ""ExpireTime"": 1571832729, ""ExpireDateTime"": ""2019-10-23T20:12:09+08:00"", ""MessageEnterWord"": ""天气"", ""MessageExitWord"": ""退出"", ""MessageKeywords"": null, ""MessageKeepTime"": 1 } }"; var dt1 = SystemTime.Now; var jsonResult = JsonConvert.DeserializeObject <CustomMessageContext>(jsonStr, new MessageContextJsonConverter <CustomMessageContext, RequestMessageBase, ResponseMessageBase>()); Console.WriteLine(SystemTime.NowDiff(dt1).TotalMilliseconds + "ms"); Assert.IsNotNull(jsonResult); Console.WriteLine(jsonResult); }
/// <summary> /// 创建动态 WebApi /// </summary> public async Task <int> BuildWebApi(IGrouping <string, KeyValuePair <string, ApiBindInfo> > apiBindGroup) { var category = apiBindGroup.Key; var dt1 = SystemTime.Now; WriteLog("", true); WriteLog($"==== Begin BuildWebApi for {category} ====", true); if (apiBindGroup.Count() == 0 || !ApiAssemblyNames.ContainsKey(category)) { WriteLog($"apiBindGroup 不存在可用对象: {category}"); return(0); } var assembleName = ApiAssemblyNames[category]; #region 动态创建程序集 var dynamicAssembly = BuildDynamicAssembly(assembleName, apiBindGroup); #endregion //TODO:开放所有类型 var apiBindFilterList = apiBindGroup.Where(z => //!z.Value.GlobalName.EndsWith("Async") //&& z.Value.MethodInfo.ReturnType != typeof(Task<>) //&& z.Value.MethodInfo.ReturnType != typeof(void) && !z.Value.MethodInfo.IsGenericMethod //SemanticApi.SemanticSend 是泛型方法 //临时过滤 IEnumerable 对象 —— Jeffrey Su 2021.06.17 && !z.Value.MethodInfo.GetParameters().Any(z => z.IsOut || z.ParameterType.Name.Contains("IEnumerable") || z.ParameterType.Name.Contains("IList`1"))) .OrderBy(z => z.Value.GlobalName) .ToArray(); //把 CommonApi 提前到头部 //Func<KeyValuePair<string, ApiBindInfo>, bool> funcCommonApi = z => z.Value.ApiBindAttribute.Name.StartsWith("CommonApi."); //var commonApiList = filterList.Where(z => funcCommonApi(z)).ToList(); //filterList.RemoveAll(z => funcCommonApi(z)); //filterList.InsertRange(0, commonApiList); int apiIndex = 0; ConcurrentDictionary <string, string> apiMethodName = new ConcurrentDictionary <string, string>(); List <Task> taskList = new List <Task>(); //预分配每个线程需要领取的任务(索引范围) var apiFilterMaxIndex = apiBindFilterList.Length - 1; //最大索引 var avgBlockCount = (int)((apiBindFilterList.Length - 1) / TaskCount); //每个线程(块)领取的平均数量 var lastEndIndex = -1; //上一个块的结束索引 for (int taskIndex = 0; taskIndex < TaskCount; taskIndex++) { if (lastEndIndex >= apiFilterMaxIndex) { break;//已经排满,终止 } var blockStart = Math.Min(lastEndIndex + 1, apiFilterMaxIndex); //当前块起始索引 var blockEnd = 0; //当前快结束索引 if (taskIndex == TaskCount - 1 || /*最后一个快,一直分配到最后(解决余数问题)*/ avgBlockCount == 0 /*如果API总数比线程数还要少,则只够一个模块*/) { blockEnd = apiFilterMaxIndex;// } else { blockEnd = Math.Min(blockStart + avgBlockCount, apiFilterMaxIndex); //非最后一个快,取平均数量 } lastEndIndex = blockEnd; //记录当前快位置 var apiTask = Task.Factory.StartNew(async() => { Range blockRange = blockStart..(blockEnd + 1); var apiBindInfoBlock = apiBindFilterList[blockRange];//截取一段,分配给当前任务 apiIndex++; #region 创建 API 方法 await BuildApiMethodForOneThread(apiBindGroup, apiBindInfoBlock, apiMethodName, dynamicAssembly.ControllerKeyName, dynamicAssembly.Tb, dynamicAssembly.FbServiceProvider, apiIndex); #endregion }); taskList.Add(apiTask.Unwrap()); } await Task.WhenAll(taskList); WriteLog("Api Task Count:" + taskList.Count, true); TypeInfo objectTypeInfo = dynamicAssembly.Tb.CreateTypeInfo(); var myType = objectTypeInfo.AsType(); WriteLog($"\t create type: {myType.Namespace} - {myType.FullName}"); //WeixinApiAssembly = myType.Assembly;//注意:此处会重复赋值相同的对象,不布偶股影响效率 ApiAssemblyCollection[category] = dynamicAssembly.Mb.Assembly;//储存程序集 var timeCost = SystemTime.NowDiff(dt1); WriteLog($"==== Finish BuildWebApi for {category} / Total Time: {timeCost.TotalMilliseconds:###,###} ms ===="); WriteLog(""); return(apiMethodName.Count); }
public ActionResult Index(string codesStr) { var codes = GetCodes(codesStr); var dt0 = SystemTime.Now; //QrCode 根目录 var qrCodeDir = Path.Combine(CO2NET.Config.RootDictionaryPath, "App_Data", "QrCode"); if (!Directory.Exists(qrCodeDir)) { Directory.CreateDirectory(qrCodeDir); } //定义文件名和路径 var tempId = SystemTime.Now.ToString("yyyy-MM-dd-HHmmss"); //本次生成唯一Id var tempDirName = $"{tempId}_{Guid.NewGuid().ToString("n")}"; //临时文件夹名 var tempZipFileName = $"{tempDirName}.zip"; //临时压缩文件名 var tempZipFileFullPath = Path.Combine(qrCodeDir, tempZipFileName); //临时压缩文件完整路径 var tempDir = Path.Combine(qrCodeDir, tempDirName); Directory.CreateDirectory(tempDir);//创建临时目录 //说明文件 var readmeFile = Path.Combine(qrCodeDir, "readme.txt"); System.IO.File.Copy(readmeFile, Path.Combine(tempDir, "readme.txt")); //便利所有二维码内容 var i = 0; foreach (var code in codes) { if (code.IsNullOrEmpty()) { continue; //过滤为空的段落 } i++; //计数器 var finalCode = code.Length > 100 ? code.Substring(0, 100) : code;//约束长度 //二维码生成开始 BitMatrix bitMatrix;//定义像素矩阵对象 bitMatrix = new MultiFormatWriter().encode(finalCode, BarcodeFormat.QR_CODE /*条码或二维码标准*/, 600 /*宽度*/, 600 /*高度*/); var bw = new ZXing.BarcodeWriterPixelData(); var pixelData = bw.Write(bitMatrix); var bitmap = new System.Drawing.Bitmap(pixelData.Width, pixelData.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb);//预绘制32bit标准的位图片 var bitmapData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, pixelData.Width, pixelData.Height) /*绘制矩形区域及偏移量*/, System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb); try { //假设位图的 row stride = 4 字节 * 图片的宽度 System.Runtime.InteropServices.Marshal.Copy(pixelData.Pixels, 0, bitmapData.Scan0, pixelData.Pixels.Length); } finally { bitmap.UnlockBits(bitmapData);//从内存 Unlock bitmap 对象 } //二维码生成结束 var fileName = Path.Combine(tempDir, $"{i}.jpg");//二维码文件名 //保存二维码 var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite); { bitmap.Save(fileStream, System.Drawing.Imaging.ImageFormat.Png); fileStream.Close();//一定要关闭文件流 } } SenparcTrace.SendCustomLog("二维码生成结束", $"耗时:{SystemTime.DiffTotalMS(dt0)} ms,临时文件:{tempZipFileFullPath}");//记录日志 var dt1 = SystemTime.Now; while (Directory.GetFiles(tempDir).Length < i + 1 /* readme.txt */ && SystemTime.NowDiff(dt1) < TimeSpan.FromSeconds(30) /*最多等待时间*/) { Thread.Sleep(1000);//重试等待时间 } ZipFile.CreateFromDirectory(tempDir, tempZipFileFullPath, CompressionLevel.Fastest, false);//创建压缩文件 var dt2 = SystemTime.Now; while (SystemTime.NowDiff(dt2) < TimeSpan.FromSeconds(10) /*最多等待时间*/) { FileStream fs = null; try { fs = new FileStream(tempZipFileFullPath, FileMode.Open, FileAccess.Read, FileShare.None); } catch { Thread.Sleep(500); continue; } if (fs != null) { return(File(fs, "application/x-zip-compressed", $"SenparcQrCode_{tempId}.zip")); //TODO:删除临时文件 } } return(Content("打包文件失败!")); }
public void DistributedCacheTest(Func <IBaseObjectCacheStrategy> cacheStrategy) { //强制使用本地缓存 CacheStrategyFactory.RegisterObjectCacheStrategy(cacheStrategy); Console.WriteLine($"当前使用缓存:{CacheStrategyFactory.GetObjectCacheStrategyInstance().GetType().FullName}"); //清空缓存 var globalMessageContext = new GlobalMessageContext <CustomMessageContext, RequestMessageBase, ResponseMessageBase>(); globalMessageContext.Restore(); //第一次请求 var dt1 = SystemTime.Now; var doc = XDocument.Parse(textRequestXml.FormatWith("TNT2", CO2NET.Helpers.DateTimeHelper.GetUnixDateTime(SystemTime.Now.UtcDateTime), SystemTime.Now.Ticks)); var messageHandler = new CustomMessageHandler(doc, postModel); var currentMessageContext = messageHandler.GetCurrentMessageContext().GetAwaiter().GetResult(); Assert.AreEqual(1, currentMessageContext.RequestMessages.Count);//初始化之后,RequestMessage 已经被记录到上下文中 Assert.AreEqual(0, currentMessageContext.ResponseMessages.Count); messageHandler.Execute(); Console.WriteLine($"第 1 次请求耗时:{SystemTime.NowDiff(dt1).TotalMilliseconds} ms"); currentMessageContext = messageHandler.GetCurrentMessageContext().GetAwaiter().GetResult(); Assert.AreEqual(1, currentMessageContext.RequestMessages.Count); Assert.AreEqual(0, currentMessageContext.ResponseMessages.Count);//默认使用异步ResponseMessage写入,有延迟(有时队列速度太快,也会执行到此处时已经写入,结果为1) //回复消息记录可以使用队列,对时间不敏感,因此需要等待队列完成记录 Thread.Sleep(500); currentMessageContext = messageHandler.GetCurrentMessageContext().GetAwaiter().GetResult(); Assert.AreEqual(1, currentMessageContext.ResponseMessages.Count);//默认使用异步ResponseMessage写入,有延迟 Console.WriteLine(currentMessageContext.ResponseMessages.Last().GetType()); Console.WriteLine(currentMessageContext.ResponseMessages.Last().ToJson()); //测试 StorageData Assert.AreEqual(1, currentMessageContext.StorageData); var lastResponseMessage = currentMessageContext.ResponseMessages.Last() as ResponseMessageText; Assert.IsNotNull(lastResponseMessage); Assert.AreEqual("来自单元测试:TNT2", lastResponseMessage.Content); //第二次请求 var dt2 = SystemTime.Now; doc = XDocument.Parse(textRequestXml.FormatWith("TNT3", CO2NET.Helpers.DateTimeHelper.GetUnixDateTime(SystemTime.Now.UtcDateTime), SystemTime.Now.Ticks)); messageHandler = new CustomMessageHandler(doc, postModel) { RecordResponseMessageSync = true //设置同步写入 ResponseMessage }; currentMessageContext = messageHandler.GetCurrentMessageContext().GetAwaiter().GetResult(); Assert.AreEqual(2, currentMessageContext.RequestMessages.Count); Assert.AreEqual(1, currentMessageContext.ResponseMessages.Count); messageHandler.Execute(); Console.WriteLine($"第 2 次请求耗时:{SystemTime.NowDiff(dt2).TotalMilliseconds} ms"); currentMessageContext = messageHandler.GetCurrentMessageContext().GetAwaiter().GetResult(); Assert.AreEqual(2, currentMessageContext.RequestMessages.Count); Assert.AreEqual(2, currentMessageContext.ResponseMessages.Count);//同步写入 ResponseMessage,没有延迟 lastResponseMessage = currentMessageContext.ResponseMessages.Last() as ResponseMessageText; Assert.IsNotNull(lastResponseMessage); Assert.AreEqual("来自单元测试:TNT3", lastResponseMessage.Content); //测试去重 var dt3 = SystemTime.Now; messageHandler = new CustomMessageHandler(doc, postModel) { RecordResponseMessageSync = true //设置同步写入 ResponseMessage }; //使用和上次同样的请求 currentMessageContext = messageHandler.GetCurrentMessageContext().GetAwaiter().GetResult(); Assert.AreEqual(2, currentMessageContext.RequestMessages.Count); Assert.AreEqual(2, currentMessageContext.ResponseMessages.Count); messageHandler.Execute(); Console.WriteLine($"第 3 次请求耗时:{SystemTime.NowDiff(dt3).TotalMilliseconds} ms"); //没有变化 currentMessageContext = messageHandler.GetCurrentMessageContext().GetAwaiter().GetResult(); Assert.AreEqual(2, currentMessageContext.RequestMessages.Count); Assert.AreEqual(2, currentMessageContext.ResponseMessages.Count); lastResponseMessage = currentMessageContext.ResponseMessages.Last() as ResponseMessageText; Assert.IsNotNull(lastResponseMessage); Assert.AreEqual("来自单元测试:TNT3", lastResponseMessage.Content); //测试最大纪录储存 Console.WriteLine("==== 循环测试开始 ===="); for (int i = 0; i < 15; i++) { var dt4 = SystemTime.Now; doc = XDocument.Parse(textRequestXml.FormatWith($"循环测试-{i}", CO2NET.Helpers.DateTimeHelper.GetUnixDateTime(SystemTime.Now.UtcDateTime) + i, SystemTime.Now.Ticks)); var maxRecordCount = 10; messageHandler = new CustomMessageHandler(doc, postModel, maxRecordCount) { RecordResponseMessageSync = true //设置同步写入 ResponseMessage }; //使用和上次同样的请求 //messageHandler.GlobalMessageContext.MaxRecordCount = 10;//在这里设置的话,Request已经插入了,无法及时触发删除多余消息的过程 messageHandler.Execute(); currentMessageContext = messageHandler.GetCurrentMessageContext().GetAwaiter().GetResult(); Assert.AreEqual(i < 7 ? i + 3 : 10, currentMessageContext.RequestMessages.Count); Assert.AreEqual(i < 7 ? i + 3 : 10, currentMessageContext.ResponseMessages.Count); Console.WriteLine($"第 {i + 1} 次循环测试请求耗时:{SystemTime.NowDiff(dt4).TotalMilliseconds} ms"); } Console.WriteLine("==== 循环测试结束 ===="); //清空 messageHandler.GlobalMessageContext.Restore(); currentMessageContext = messageHandler.GetCurrentMessageContext().GetAwaiter().GetResult(); Assert.AreEqual(0, currentMessageContext.RequestMessages.Count); //回复消息记录可以使用队列,对时间不敏感,因此需要等待队列完成记录 Thread.Sleep(300); Assert.AreEqual(0, currentMessageContext.ResponseMessages.Count); Console.WriteLine(); }
public async Task <IActionResult> RunTest() { var sb = new StringBuilder(); try { var containerCacheStrategy = ContainerCacheStrategyFactory.GetContainerCacheStrategyInstance() /*.ContainerCacheStrategy*/; var currentSystemCacheStrategy = containerCacheStrategy.BaseCacheStrategy(); sb.AppendFormat($"当前系统缓存策略:{containerCacheStrategy.GetType().Name}<br /><br />"); var currentSystemContainerCacheStrategy = ContainerCacheStrategyFactory.GetContainerCacheStrategyInstance(); sb.AppendFormat($"当前系统容器缓存(领域缓存)策略:{currentSystemContainerCacheStrategy.GetType().Name}<br /><br />"); var caches = new Dictionary <IBaseObjectCacheStrategy, IContainerCacheStrategy> { { LocalObjectCacheStrategy.Instance, LocalContainerCacheStrategy.Instance } }; try { caches[RedisObjectCacheStrategy.Instance] = RedisContainerCacheStrategy.Instance; } catch (Exception) { sb.Append("==== 当前系统未配置 Reis,跳过 Redis测试 ====<br /><br />"); } var cacheExpire = TimeSpan.FromSeconds(1); foreach (var cacheSet in caches) { bool testSuccess = false; TestContainerBag1 cacheBag = null; var baseCache = cacheSet.Key; var containerCache = cacheSet.Value; sb.AppendFormat($"==== 开始指定调用缓存策略:{baseCache.GetType().Name} ====<br /><br />"); sb.Append($"----- 测试写入(先异步后同步) -----<br />"); var shortBagKey = SystemTime.Now.ToString("yyyyMMdd-HHmmss") + "." + cacheExpire.GetHashCode(); //创建不重复的Key var finalBagKey = baseCache.GetFinalKey(ContainerHelper.GetItemCacheKey(typeof(TestContainerBag1), shortBagKey)); //获取最终缓存中的键 var bag = new TestContainerBag1() { Key = shortBagKey, DateTime = SystemTime.Now }; var dt1 = SystemTime.Now; await baseCache.SetAsync(finalBagKey, bag, expiry : null, true);//不设置过期时间 sb.Append($"异步写入完成:{SystemTime.NowDiff(dt1).TotalMilliseconds.ToString("f4")} ms<br />"); dt1 = SystemTime.Now; baseCache.Set(finalBagKey, bag, expiry: null, true);//不设置过期时间 sb.Append($"同步写入完成:{SystemTime.NowDiff(dt1).TotalMilliseconds.ToString("f4")} ms<br />"); sb.Append($"----- 写入测试完成 -----<br /><br />"); sb.Append($"----- 检查缓存读取(先同步后异步) -----<br />"); dt1 = SystemTime.Now; cacheBag = baseCache.Get <TestContainerBag1>(finalBagKey, true); sb.Append($"同步读取完成:{SystemTime.NowDiff(dt1).TotalMilliseconds.ToString("f4")} ms<br />"); dt1 = SystemTime.Now; cacheBag = await baseCache.GetAsync <TestContainerBag1>(finalBagKey, true); testSuccess = cacheBag != null; sb.Append($"异步读取完成:{SystemTime.NowDiff(dt1).TotalMilliseconds.ToString("f4")} ms<br />"); testSuccess &= cacheBag != null && cacheBag.DateTime == bag.DateTime && bag.Key == shortBagKey; sb.Append($"----- 检查结果:{(testSuccess ? "成功" : "失败")} -----<br /><br />"); sb.Append($"----- 容器缓存(领域缓存)修改测试 -----<br />"); dt1 = SystemTime.Now; cacheBag.DateTime = SystemTime.Now; await TestContainer1.UpdateAsync(cacheBag, cacheExpire);//设置过期时间 sb.Append($"写入完成:{SystemTime.NowDiff(dt1).TotalMilliseconds.ToString("f4")} ms<br />"); var dt2 = SystemTime.Now; var containerResult1 = await TestContainer1.TryGetItemAsync <TestContainerBag1>(shortBagKey, z => z); sb.Append($"使用 ContainerCacheStrategy 读取完成:{SystemTime.NowDiff(dt2).TotalMilliseconds.ToString("f4")} ms<br />"); dt2 = SystemTime.Now; var containerResult2 = await baseCache.GetAsync <TestContainerBag1>(finalBagKey, true); sb.Append($"使用 BaseContainerStrategy 读取完成:{SystemTime.NowDiff(dt2).TotalMilliseconds.ToString("f4")} ms<br />"); testSuccess = containerResult1 != null && containerResult2 != null && containerResult1.Key == containerResult2.Key && containerResult1.DateTime == containerResult2.DateTime; sb.Append($"----- 测试结果:{(testSuccess ? "成功" : "失败")}(总耗时:{SystemTime.NowDiff(dt1).TotalMilliseconds.ToString("f4")} ms) -----<br /><br />"); sb.Append($"----- 检查缓存过期 -----<br />"); var sleepTime = cacheExpire.Add(TimeSpan.FromMilliseconds(500)); sb.Append($"线程休眠:{sleepTime.TotalSeconds.ToString("f2")}s<br />"); await Task.Delay(sleepTime); cacheBag = await baseCache.GetAsync <TestContainerBag1>(finalBagKey, true); sb.Append($"----- 检查结果:{(cacheBag == null ? "成功" : "失败")} -----<br /><br />"); sb.Append($"----- 检查缓存删除 -----<br />"); await baseCache.UpdateAsync(finalBagKey, bag, cacheExpire, true); cacheBag = await baseCache.GetAsync <TestContainerBag1>(finalBagKey, true); testSuccess = cacheBag != null; sb.Append($"写入待删除项目:{(cacheBag != null ? "成功" : "失败")}<br />"); dt1 = SystemTime.Now; await baseCache.RemoveFromCacheAsync(finalBagKey, true); sb.Append($"删除项目({SystemTime.NowDiff(dt1).TotalMilliseconds.ToString("f4")} ms)<br />"); cacheBag = await baseCache.GetAsync <TestContainerBag1>(finalBagKey, true); sb.Append($"----- 删除结果检查:{(cacheBag == null ? "成功" : "失败")} -----<br /><br /><br />"); } } catch (Exception ex) { sb.Append($@"===== 发生异常:{ex.Message} =====<br /> {ex.StackTrace.ToString()}<br /> {ex.InnerException?.StackTrace.ToString()}<br />"); } return(Content(sb.ToString())); }
public async Task <IActionResult> RunTest(int id = 0) { var sb = new StringBuilder(); try { //选择要测试的缓存类型 IContainerCacheStrategy containerCacheStrategy; switch (id) { case 1: containerCacheStrategy = Senparc.Weixin.Cache.Redis.RedisContainerCacheStrategy.Instance; break; case 2: containerCacheStrategy = Senparc.Weixin.Cache.CsRedis.RedisContainerCacheStrategy.Instance; break; case -1: containerCacheStrategy = ContainerCacheStrategyFactory.GetContainerCacheStrategyInstance(); break; default: containerCacheStrategy = Senparc.Weixin.Cache.LocalContainerCacheStrategy.Instance; break; } var baseCache = containerCacheStrategy.BaseCacheStrategy(); sb.AppendFormat($"当前测试缓存策略:{baseCache.GetType().FullName}<br /><br />"); var containerCache = ContainerCacheStrategyFactory.GetContainerCacheStrategyInstance(); sb.AppendFormat($"当前测试容器缓存(领域缓存)策略:{containerCache.GetType().FullName}<br /><br />"); var cacheExpire = TimeSpan.FromSeconds(1); const string successTag = "<span style=\"color:green\">成功</span>"; const string faildTag = "<span style=\"color:red\">失败</span>"; bool testSuccess = false; TestContainerBag1 cacheBag = null; sb.AppendFormat($"==== 开始指定调用缓存策略:{baseCache.GetType().FullName} ====<br /><br />"); sb.Append($"----- 测试写入(先异步后同步) -----<br />"); var shortBagKey = SystemTime.Now.ToString("yyyyMMdd-HHmmss") + "." + cacheExpire.GetHashCode(); //创建不重复的Key var finalBagKey = baseCache.GetFinalKey(ContainerHelper.GetItemCacheKey(typeof(TestContainerBag1), shortBagKey)); //获取最终缓存中的键 var bag = new TestContainerBag1() { Key = shortBagKey, DateTime = SystemTime.Now }; var dt1 = SystemTime.Now; await baseCache.SetAsync(finalBagKey, bag, expiry : null, true);//不设置过期时间 sb.Append($"异步写入完成:{SystemTime.NowDiff(dt1).TotalMilliseconds.ToString("f4")} ms<br />"); dt1 = SystemTime.Now; baseCache.Set(finalBagKey, bag, expiry: null, true);//不设置过期时间 sb.Append($"同步写入完成:{SystemTime.NowDiff(dt1).TotalMilliseconds.ToString("f4")} ms<br />"); sb.Append($"----- 写入测试完成 -----<br /><br />"); sb.Append($"----- 检查缓存读取(先同步后异步) -----<br />"); dt1 = SystemTime.Now; cacheBag = baseCache.Get <TestContainerBag1>(finalBagKey, true); sb.Append($"同步读取完成:{SystemTime.NowDiff(dt1).TotalMilliseconds.ToString("f4")} ms<br />"); dt1 = SystemTime.Now; cacheBag = await baseCache.GetAsync <TestContainerBag1>(finalBagKey, true); testSuccess = cacheBag != null; sb.Append($"异步读取完成:{SystemTime.NowDiff(dt1).TotalMilliseconds.ToString("f4")} ms<br />"); testSuccess &= cacheBag != null && cacheBag.DateTime == bag.DateTime && bag.Key == shortBagKey; sb.Append($"----- 检查结果:{(testSuccess ? successTag : faildTag)} -----<br /><br />"); sb.Append($"----- 容器缓存(领域缓存)修改测试 -----<br />"); dt1 = SystemTime.Now; cacheBag.DateTime = SystemTime.Now; await TestContainer1.UpdateAsync(cacheBag, cacheExpire);//设置过期时间 sb.Append($"写入完成:{SystemTime.NowDiff(dt1).TotalMilliseconds.ToString("f4")} ms<br />"); var dt2 = SystemTime.Now; var containerResult1 = await TestContainer1.TryGetItemAsync <TestContainerBag1>(shortBagKey, z => z); sb.Append($"使用 ContainerCacheStrategy 读取完成:{SystemTime.NowDiff(dt2).TotalMilliseconds.ToString("f4")} ms<br />"); dt2 = SystemTime.Now; var containerResult2 = await baseCache.GetAsync <TestContainerBag1>(finalBagKey, true); sb.Append($"使用 BaseContainerStrategy 读取完成:{SystemTime.NowDiff(dt2).TotalMilliseconds.ToString("f4")} ms<br />"); testSuccess = containerResult1 != null && containerResult2 != null && containerResult1.Key == containerResult2.Key && containerResult1.DateTime == containerResult2.DateTime; sb.Append($"----- 测试结果:{(testSuccess ? successTag : faildTag)}(总耗时:{SystemTime.NowDiff(dt1).TotalMilliseconds.ToString("f4")} ms) -----<br /><br />"); sb.Append($"----- 检查缓存过期 -----<br />"); var sleepTime = cacheExpire.Add(TimeSpan.FromMilliseconds(500)); sb.Append($"线程休眠:{sleepTime.TotalSeconds.ToString("f2")}s<br />"); await Task.Delay(sleepTime); cacheBag = await baseCache.GetAsync <TestContainerBag1>(finalBagKey, true); sb.Append($"----- 检查结果:{(cacheBag == null ? successTag : faildTag)} -----<br /><br />"); //sb.Append($"----- 检查缓存删除 -----<br />"); //await baseCache.UpdateAsync(finalBagKey, bag, cacheExpire, true); //cacheBag = await baseCache.GetAsync<TestContainerBag1>(finalBagKey, true); //testSuccess = cacheBag != null; //sb.Append($"写入待删除项目:{(cacheBag != null ? successTag : faildTag)}<br />"); //dt1 = SystemTime.Now; //await baseCache.RemoveFromCacheAsync(finalBagKey, true); //sb.Append($"删除项目({SystemTime.NowDiff(dt1).TotalMilliseconds.ToString("f4")} ms)<br />"); //cacheBag = await baseCache.GetAsync<TestContainerBag1>(finalBagKey, true); //sb.Append($"----- 删除结果检查:{(cacheBag == null ? successTag : faildTag)} -----<br /><br /><br />"); } catch (Exception ex) { sb.Append($@"===== 发生异常:{ex.Message} =====<br /> {ex.StackTrace.ToString()}<br /> {ex.InnerException?.StackTrace.ToString()}<br />"); } return(Content(sb.ToString())); }
public ActionResult Index(string codesStr) { var codes = codesStr.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); var i = 0; //限制个数 if (codes.Length > 200) { codes = codes.Take(100).ToArray(); } var qrCodeDir = Path.Combine(CO2NET.Config.RootDictionaryPath, "App_Data", "QrCode"); if (!Directory.Exists(qrCodeDir)) { Directory.CreateDirectory(qrCodeDir); } //定义文件名和路径 var tempId = SystemTime.Now.ToString("yyyy-MM-dd-HHmmss"); var tempDirName = $"{tempId}_{Guid.NewGuid().ToString("n")}"; var tempZipFileName = $"{tempDirName}.zip"; var tempZipFileFullPath = Path.Combine(qrCodeDir, tempZipFileName); var tempDir = Path.Combine(qrCodeDir, tempDirName); Directory.CreateDirectory(tempDir);//创建临时目录 var readmeFile = Path.Combine(qrCodeDir, "readme.txt"); System.IO.File.Copy(readmeFile, Path.Combine(tempDir, "readme.txt")); //便利所有二维码内容 foreach (var code in codes) { if (code.IsNullOrEmpty()) { continue; } i++; var finalCode = code.Length > 100 ? code.Substring(0, 100) : code;//约束长度 BitMatrix bitMatrix; bitMatrix = new MultiFormatWriter().encode(finalCode, BarcodeFormat.QR_CODE, 600, 600); var bw = new ZXing.BarcodeWriterPixelData(); var pixelData = bw.Write(bitMatrix); var bitmap = new System.Drawing.Bitmap(pixelData.Width, pixelData.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb); var bitmapData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, pixelData.Width, pixelData.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb); try { // we assume that the row stride of the bitmap is aligned to 4 byte multiplied by the width of the image System.Runtime.InteropServices.Marshal.Copy(pixelData.Pixels, 0, bitmapData.Scan0, pixelData.Pixels.Length); } finally { bitmap.UnlockBits(bitmapData); } var fileName = Path.Combine(tempDir, $"{i}.jpg"); var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite); { bitmap.Save(fileStream, System.Drawing.Imaging.ImageFormat.Png); fileStream.Close(); } } SenparcTrace.SendCustomLog("二维码生成结束", tempZipFileFullPath); var dt1 = SystemTime.Now; while (Directory.GetFiles(tempDir).Length < i + 1 /* readme.txt */ && SystemTime.NowDiff(dt1) < TimeSpan.FromSeconds(30) /*最多等待时间*/) { Thread.Sleep(1000); } ZipFile.CreateFromDirectory(tempDir, tempZipFileFullPath, CompressionLevel.Fastest, false); var dt2 = SystemTime.Now; while (SystemTime.NowDiff(dt2) < TimeSpan.FromSeconds(10) /*最多等待时间*/) { FileStream fs = null; try { fs = new FileStream(tempZipFileFullPath, FileMode.Open, FileAccess.Read, FileShare.None); } catch { Thread.Sleep(500); continue; } if (fs != null) { return(File(fs /*$"~/App_Data/QrCode/{tempZipFileName}"*/ /*tempZipFileFullPath*/, "application/x-zip-compressed", $"SenparcQrCode_{tempId}.zip")); } } return(Content("打包文件失败!")); }