using Backend.Models; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; using Quartz; using Repository.BackendRepository.Interface; using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Text; using System.Text.Json; using System.Threading.Tasks; namespace BackendWorkerService.Quartz.Jobs { [DisallowConcurrentExecution] class DataDeliveryJob : IJob { private readonly ILogger logger; private readonly IBackgroundServiceRepository backgroundServiceRepository; public DataDeliveryJob( ILogger logger, IBackgroundServiceRepository backgroundServiceRepository) { this.logger = logger; this.backgroundServiceRepository = backgroundServiceRepository; } public async Task Execute(IJobExecutionContext context) { Dictionary insertLog = new Dictionary() { { "@task_id", 0 }, { "@log_level", "" }, { "@log_content", "" } }; try { logger.LogInformation("【DataDeliveryJob】【任務開始】"); insertLog["@log_level"] = $@"INFO"; insertLog["@log_content"] = $@"【DataDeliveryJob】任務開始"; await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log"); //找出所有要派送的資料 string sWhere = @"is_complete = 0 AND task_type = @Task_type AND repeat_times < 10"; var backgroundServiceTasks = await backgroundServiceRepository.GetAllAsync("background_service_task", sWhere, new { Task_type = BackgroundServiceTaskType.data_delivery }); if (backgroundServiceTasks.Count == 0) { logger.LogInformation("【DataDeliveryJob】【查無任務列表】"); insertLog["@log_level"] = $@"INFO"; insertLog["@log_content"] = $@"【DataDeliveryJob】查無任務列表"; await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log"); } else { List> updateObjs = new List>(); foreach (var task in backgroundServiceTasks) { var DateTimeNow = DateTime.Now; Dictionary updateObj = new Dictionary() { { "Id", task.Id }, { "@repeat_times", 0 }, { "@is_complete", 0 }, { "@fail_reason", null }, { "@complete_at", null }, { "@updated_at", DateTimeNow } }; insertLog["@task_id"] = task.Id; //var parameters = JsonSerializer.Deserialize>(task.Target_data); try { logger.LogInformation("【DataDeliveryJob】【開始派送】[棟別IP]:{0}", task.Target_ip); insertLog["@log_level"] = $@"INFO"; insertLog["@log_content"] = $@"開始派送"; await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log"); var boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x"); var boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); var endBoundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--"); HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create($"http://{task.Target_ip}/api/ReceiveDataDelivery/GetData"); Postrequest.ContentType = "multipart/form-data; boundary=" + boundary; Postrequest.Method = "POST"; if (!string.IsNullOrEmpty(task.Target_table)) { using (Stream requestStream = Postrequest.GetRequestStream()) { //Id requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); string task_id = "Content-Disposition: form-data; name=\"" + "Id" + "\"\r\n\r\n" + task.Id; byte[] task_id_bytes = System.Text.Encoding.UTF8.GetBytes(task_id); requestStream.Write(task_id_bytes, 0, task_id_bytes.Length); //Target Table requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); string target_table = "Content-Disposition: form-data; name=\"" + "TargetTable" + "\"\r\n\r\n" + task.Target_table; byte[] target_table_bytes = System.Text.Encoding.UTF8.GetBytes(target_table); requestStream.Write(target_table_bytes, 0, target_table_bytes.Length); //mode requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); string target_mode = "Content-Disposition: form-data; name=\"" + "mode" + "\"\r\n\r\n" + task.Mode; byte[] target_mode_bytes = System.Text.Encoding.UTF8.GetBytes(target_mode); requestStream.Write(target_mode_bytes, 0, target_mode_bytes.Length); //Target data requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); string target_data = "Content-Disposition: form-data; name=\"" + "TargetData" + "\"\r\n\r\n" + task.Target_data; byte[] target_data_bytes = System.Text.Encoding.UTF8.GetBytes(target_data); requestStream.Write(target_data_bytes, 0, target_data_bytes.Length); //解析Files if (task.Target_files != null) { var target_files = JsonSerializer.Deserialize>(task.Target_files); var file_index = 0; foreach (var file in target_files) { //file Folder requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); string file_folder = "Content-Disposition: form-data; name=\"" + $"FileInfos[{file_index}].Folder" + "\"\r\n\r\n" + file.Folder; byte[] file_folder_bytes = System.Text.Encoding.UTF8.GetBytes(file_folder); requestStream.Write(file_folder_bytes, 0, file_folder_bytes.Length); //file OriginalFileName requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); string orig_file_name = "Content-Disposition: form-data; name=\"" + $"FileInfos[{file_index}].OriginalFileName" + "\"\r\n\r\n" + file.OriginalFileName; byte[] orig_file_name_bytes = System.Text.Encoding.UTF8.GetBytes(orig_file_name); requestStream.Write(orig_file_name_bytes, 0, orig_file_name_bytes.Length); //file FileName requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); string file_name = "Content-Disposition: form-data; name=\"" + $"FileInfos[{file_index}].FileName" + "\"\r\n\r\n" + file.FileName; byte[] file_name_bytes = System.Text.Encoding.UTF8.GetBytes(file_name); requestStream.Write(file_name_bytes, 0, file_name_bytes.Length); //取得Content-Type var content_type = string.Empty; string ext = Path.GetExtension(file.File); using (Microsoft.Win32.RegistryKey registryKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext)) { if (registryKey != null) { var value = registryKey.GetValue("Content Type"); if (value != null) { content_type = value.ToString(); } } } if (file.File != null) { string file_header = "Content-Disposition: form-data; name=\"" + $"FileInfos[{file_index}].File" + "\"; filename=\"" + file.FileName + "\"\r\nContent-Type: " + content_type + "\r\n\r\n"; byte[] file_header_bytes = System.Text.Encoding.UTF8.GetBytes(file_header); requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); requestStream.Write(file_header_bytes, 0, file_header_bytes.Length); byte[] buffer = new byte[32768]; int bytesRead; // upload from file using (FileStream fileStream = File.OpenRead(file.File)) { while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) requestStream.Write(buffer, 0, bytesRead); fileStream.Close(); } } } } requestStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); requestStream.Close(); } } HttpWebResponse response = (HttpWebResponse)Postrequest.GetResponse(); var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd(); var statusNumber = (int)response.StatusCode; if (statusNumber != 200) { logger.LogError("【DataDeliveryJob】【派送失敗】[棟別IP]:{0}", task.Target_ip); logger.LogError("【DataDeliveryJob】【派送失敗】[response]:{0}", responseString); updateObj["@repeat_times"] = task.Repeat_times + 1; updateObj["@fail_reason"] = responseString; insertLog["@log_level"] = $@"ERR"; insertLog["@log_content"] = $@"派送失敗 - [失敗原因]:{responseString}"; await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log"); } else { //解析回傳內容 var final = JObject.Parse(responseString); var code = final["code"].ToString(); if (code == "0000") { logger.LogInformation("【DataDeliveryJob】【派送成功】[棟別IP]:{0}", task.Target_ip); updateObj["@repeat_times"] = task.Repeat_times; updateObj["@is_complete"] = 1; updateObj["@complete_at"] = DateTime.Now; insertLog["@log_level"] = $@"INFO"; insertLog["@log_content"] = $@"派送成功"; await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log"); } else { logger.LogError("【DataDeliveryJob】【派送失敗】[棟別IP]:{0}", task.Target_ip); logger.LogError("【DataDeliveryJob】【派送失敗】[response]:{0}", responseString); updateObj["@repeat_times"] = task.Repeat_times + 1; updateObj["@fail_reason"] = responseString; insertLog["@log_level"] = $@"ERR"; insertLog["@log_content"] = $@"派送失敗 - [失敗原因]:{responseString}"; await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log"); } } } catch (Exception exception) { logger.LogError("【DataDeliveryJob】【派送失敗】[棟別IP]:{0}", task.Target_ip); logger.LogError("【DataDeliveryJob】【派送失敗】[Exception]:{0}", exception.ToString()); updateObj["@repeat_times"] = task.Repeat_times + 1; updateObj["@fail_reason"] = exception.ToString(); insertLog["@log_level"] = $@"ERR"; insertLog["@log_content"] = $@"派送失敗 - [失敗原因(Exception)]:{exception.ToString()}"; await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log"); } updateObjs.Add(updateObj); } await backgroundServiceRepository.UpdateListByCustomTable(updateObjs, "background_service_task", "id = @Id"); logger.LogInformation("【DataDeliveryJob】【任務完成】"); insertLog["@task_id"] = 0; insertLog["@log_level"] = $@"INFO"; insertLog["@log_content"] = $@"任務完成"; await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log"); } } catch (Exception exception) { logger.LogError("【DataDeliveryJob】【任務失敗】"); logger.LogError("【DataDeliveryJob】【任務失敗】[Exception]:{0}", exception.ToString()); insertLog["@task_id"] = 0; insertLog["@log_level"] = $@"ERR"; insertLog["@log_content"] = $@"任務失敗"; await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log"); } } } }