270 lines
16 KiB
C#
270 lines
16 KiB
C#
|
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<DataDeliveryJob> logger;
|
|||
|
private readonly IBackgroundServiceRepository backgroundServiceRepository;
|
|||
|
|
|||
|
public DataDeliveryJob(
|
|||
|
ILogger<DataDeliveryJob> logger,
|
|||
|
IBackgroundServiceRepository backgroundServiceRepository)
|
|||
|
{
|
|||
|
this.logger = logger;
|
|||
|
this.backgroundServiceRepository = backgroundServiceRepository;
|
|||
|
}
|
|||
|
|
|||
|
public async Task Execute(IJobExecutionContext context)
|
|||
|
{
|
|||
|
Dictionary<string, object> insertLog = new Dictionary<string, object>()
|
|||
|
{
|
|||
|
{ "@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<BackgroundServiceTask>("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<Dictionary<string, object>> updateObjs = new List<Dictionary<string, object>>();
|
|||
|
foreach (var task in backgroundServiceTasks)
|
|||
|
{
|
|||
|
var DateTimeNow = DateTime.Now;
|
|||
|
Dictionary<string, object> updateObj = new Dictionary<string, object>()
|
|||
|
{
|
|||
|
{ "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<Dictionary<string, object>>(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<List<Backend.Models.FileInfo>>(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");
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
}
|