|
@@ -0,0 +1,186 @@
|
|
|
+using CsvUploader.Func;
|
|
|
+using CsvUploader.Model;
|
|
|
+using Dapper;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Data.SqlClient;
|
|
|
+using System.IO;
|
|
|
+using System.Linq;
|
|
|
+using System.Text;
|
|
|
+using System.Threading.Tasks;
|
|
|
+
|
|
|
+namespace CsvUploader
|
|
|
+{
|
|
|
+ class CsvUploadTask
|
|
|
+ {
|
|
|
+ public CsvUploadTask(Model.UploadTask uploadTaskSetting)
|
|
|
+ {
|
|
|
+ this._uploadTaskSetting = uploadTaskSetting;
|
|
|
+ _uploadRecordService = new UploadRecordService(uploadTaskSetting.Name);
|
|
|
+ _fileSystemWatcher = new FileSystemWatcher(uploadTaskSetting.Folder);
|
|
|
+ _fileSystemWatcher.Changed += _fileSystemWatcher_Changed;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Start()
|
|
|
+ {
|
|
|
+ _ = StartAsync();
|
|
|
+ }
|
|
|
+
|
|
|
+ public async Task StartAsync()
|
|
|
+ {
|
|
|
+ _fileSystemWatcher.EnableRaisingEvents = true;
|
|
|
+ InitialUploadTask = CheckAndUpload();
|
|
|
+ }
|
|
|
+
|
|
|
+ private readonly UploadTask _uploadTaskSetting;
|
|
|
+ private readonly UploadRecordService _uploadRecordService;
|
|
|
+ private readonly FileSystemWatcher _fileSystemWatcher;
|
|
|
+
|
|
|
+ private Task InitialUploadTask = null;
|
|
|
+ private List<string> unUploadFiles = new List<string>();
|
|
|
+
|
|
|
+ private async Task CheckAndUpload()
|
|
|
+ {
|
|
|
+ var files = Directory.GetFiles(_uploadTaskSetting.Folder, "*", SearchOption.AllDirectories);
|
|
|
+ foreach (var file in files)
|
|
|
+ {
|
|
|
+ await TryUploadFileRecord(file);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private async void _fileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
|
|
|
+ {
|
|
|
+ if (e.ChangeType != WatcherChangeTypes.Changed)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (InitialUploadTask is null ||
|
|
|
+ !InitialUploadTask.IsCompleted)
|
|
|
+ {
|
|
|
+ unUploadFiles.Add(e.Name);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var file in unUploadFiles)
|
|
|
+ {
|
|
|
+ await TryUploadFileRecord(e.Name);
|
|
|
+ }
|
|
|
+
|
|
|
+ //check file or folder
|
|
|
+ await TryUploadFileRecord(e.FullPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ private async ValueTask TryUploadFileRecord(string file)
|
|
|
+ {
|
|
|
+ var fileType = Path.GetExtension(file);
|
|
|
+ if (fileType != ".csv")
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ var fileName = Path.GetFileName(file);
|
|
|
+ var updateTime = File.GetLastWriteTime(file);
|
|
|
+ var uploadTime = _uploadRecordService.TryGetUploadDateTime(fileName);
|
|
|
+
|
|
|
+ if (uploadTime == null ||
|
|
|
+ uploadTime < updateTime)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (await UploadFileRecord(file))
|
|
|
+ {
|
|
|
+ _uploadRecordService.SetUploadDateTime(file, updateTime);
|
|
|
+ Console.WriteLine($"File {fileName} record uploaded");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Console.WriteLine($"File {fileName} record upload FAIL");
|
|
|
+ }
|
|
|
+ catch(Exception e)
|
|
|
+ {
|
|
|
+ //Console.WriteLine(e.StackTrace);
|
|
|
+ Console.WriteLine(e.Message);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private async Task<bool> UploadFileRecord(string file)
|
|
|
+ {
|
|
|
+ UploadData data = ParseUploadData(file);
|
|
|
+ if (data is null)
|
|
|
+ {
|
|
|
+ throw new FormatException($"file {file} formate error");
|
|
|
+ }
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ string cmd = CreateSqlCmd(data);
|
|
|
+ using (var dbConn = new SqlConnection(_uploadTaskSetting.SqlConnectionString))
|
|
|
+ {
|
|
|
+ dbConn.Open();
|
|
|
+ var cnt = await dbConn.ExecuteAsync(cmd);
|
|
|
+
|
|
|
+ return cnt > 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ Console.WriteLine(e.Message);
|
|
|
+ throw new Exception($"Task {_uploadTaskSetting.Name} upload fail", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private UploadData ParseUploadData(string file)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var toReturn = new UploadData();
|
|
|
+ var lines = File.ReadAllLines(file);
|
|
|
+ var csvPairs = new Dictionary<string, string>();
|
|
|
+
|
|
|
+ csvPairs.AddSimpleData(lines)
|
|
|
+ .AddTablesData(_uploadTaskSetting.Tables)
|
|
|
+ .CleanDataTail()
|
|
|
+ .TryValueConvert(_uploadTaskSetting.IsPassToInt);
|
|
|
+
|
|
|
+ var columnNames = _uploadTaskSetting.CsvColumnNames.ToList();
|
|
|
+ columnNames = columnNames.ReplaceByRule(csvPairs).ToList();
|
|
|
+
|
|
|
+ UpdateUploadData(toReturn, csvPairs, columnNames);
|
|
|
+
|
|
|
+ return toReturn;
|
|
|
+ }
|
|
|
+ catch (IOException e)
|
|
|
+ {
|
|
|
+ throw new Exception($"File {file} in use", e);
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void UpdateUploadData(UploadData toReturn, Dictionary<string, string> csvPairs, List<string> columnNames)
|
|
|
+ {
|
|
|
+ foreach (var pair in csvPairs)
|
|
|
+ {
|
|
|
+ if (columnNames.Contains(pair.Key))
|
|
|
+ {
|
|
|
+ var index = columnNames.IndexOf(pair.Key);
|
|
|
+ toReturn.ColumnNames.Add(_uploadTaskSetting.DbColumnNames[index]);
|
|
|
+ toReturn.Datas.Add(pair.Value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private string CreateSqlCmd(UploadData data)
|
|
|
+ {
|
|
|
+ string cmd = $"INSERT INTO {_uploadTaskSetting.TableName} (";
|
|
|
+ cmd += String.Join(", ", data.ColumnNames.Select(x => $"[{x}]"));
|
|
|
+ cmd += ") VALUES (";
|
|
|
+ cmd += String.Join(", ", data.Datas.Select(x => $"'{x}'"));
|
|
|
+ cmd += $")";
|
|
|
+ return cmd;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|