iFileProxy/src/Helpers/DatabaseHelper.cs

343 lines
13 KiB
C#

using iFileProxy.Config;
using Serilog;
using System.Data;
using System.Text.Json;
using MySql.Data.MySqlClient;
using iFileProxy.Models;
using Newtonsoft.Json;
namespace iFileProxy.Helpers
{
public class DatabaseHelper
{
Database _db;
AppConfig _appConfig;
private readonly static Serilog.ILogger _logger = Log.Logger.ForContext<DatabaseHelper>();
Dictionary<string, DB> _dbDictionary = [];
public DatabaseHelper(AppConfig appConfig)
{
_logger.Information("Initializing DatabaseHelper...");
_db = appConfig.Database;
_appConfig = appConfig;
try
{
_logger.Information("Done.");
}
catch (Exception e)
{
_logger.Fatal($"程序异常: {e.Message}");
}
LoadDbDict();
}
/// <summary>
/// 加载数据库描述字典
/// </summary>
public void LoadDbDict()
{
foreach (DB item in _db.Databases)
{
_dbDictionary.Add(item.Description, item);
_logger.Debug($"Db Config: {item.Description} <=> {item.DatabaseName} Loaded.");
}
}
/// <summary>
/// 获取一个指定数据库的连接
/// </summary>
/// <param name="db_desc">数据库描述字段 对应AppConfig的description字段</param>
/// <returns></returns>
/// <exception cref="Exception">若某些不允许为空的字段出现空值 则抛出此异常</exception>
///
public MySqlConnection GetAndOpenDBConn(string db_desc)
{
if (!_dbDictionary.TryGetValue(db_desc, out DB Db))
{
throw new Exception($"未找到与 {db_desc} 相匹配的数据库配置");
}
var db_user = Db.User ?? _db.Common.User;
var db_password = Db.Password ?? _db.Common.Password;
var db_host = Db.Host ?? _db.Common.Host;
var db_port = Db.Port ?? _db.Common.Port;
if (db_user == null || db_password == null || db_host == null || db_port == null)
throw new NoNullAllowedException("数据库配置获取失败,不允许为空的字段出现空值");
string db_connstr = $"server={db_host};user={db_user};database={Db.DatabaseName};port={db_port};password={db_password};Pooling=true;MaximumPoolSize=500;";
MySqlConnection conn;
try
{
conn = new MySqlConnection(db_connstr);
conn.Open();
}
catch (Exception ex)
{
_logger.Fatal($"获取Mysql连接时出现异常:{ex.Message}");
throw;
}
return conn;
}
public bool TestDbConfig()
{
foreach (var db in _dbDictionary)
{
_logger.Information($"[程序启动前配置验证] 正在测试数据库配置: {db.Key} ...");
MySqlConnection dbConn = new();
try
{
dbConn = GetAndOpenDBConn(db.Key);
_logger.Information($"succ.");
}
catch (Exception)
{
_logger.Fatal($"=========== 数据库: {db.Key} 测试失败! ===========");
return false;
}
finally
{
dbConn.Close();
}
}
return true;
}
/// <summary>
/// 获取一个json格式的数据表
/// </summary>
/// <param name="sql"></param>
/// <param name="conn"></param>
/// <returns></returns>
public static string QueryTableData(MySqlCommand sqlCmd)
{
DataTable dataTable = new();
using (MySqlDataAdapter adapter = new (sqlCmd))
adapter.Fill(dataTable);
return JsonConvert.SerializeObject(dataTable);
}
/// <summary>
/// 获取一个json格式的数据表
/// </summary>
/// <param name="sql"></param>
/// <param name="conn"></param>
/// <returns></returns>
public string QueryTableData(string sql,string dbConfName)
{
DataTable dataTable = new();
using (MySqlDataAdapter adapter = new(new MySqlCommand(sql,GetAndOpenDBConn(dbConfName))))
adapter.Fill(dataTable);
return JsonConvert.SerializeObject(dataTable);
}
/// <summary>
/// 内部查询数据专用 当此方法暴露给C端可能造成sql注入等安全问题
/// </summary>
/// <param name="sql">SQL语句</param>
/// <param name="dbConfName">配置文件中的Description字段</param>
/// <returns>影响的行数</returns>
public int Query(string sql, string dbConfName)
{
using MySqlCommand sqlCmd = new (sql, GetAndOpenDBConn(dbConfName));
int n = sqlCmd.ExecuteNonQuery();
_logger.Debug($"查询完成, 受影响的行数: {n}");
return n;
}
public string GetTaskListByIP(string ipAddr)
{
string sql = $"SELECT * FROM t_tasks_info WHERE client_ip = @ip_addr";
MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
try
{
using MySqlCommand sqlCmd = new (sql,conn);
sqlCmd.Parameters.AddWithValue("@ip_addr", ipAddr);
return QueryTableData(sqlCmd);
}
catch (Exception e)
{
_logger.Error($"无法获取任务列表: {e.Message}");
throw;
}
finally { conn.Close(); }
}
public string GetTaskInfoByTid(string tid)
{
string sql = $"SELECT * FROM t_tasks_info WHERE `tid` =@tid";
MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
try
{
using MySqlCommand sqlCmd = new(sql, conn);
sqlCmd.Parameters.AddWithValue("@tid", tid);
return QueryTableData(sqlCmd);
}
catch (Exception e)
{
_logger.Error($"无法获取任务信息: {e.Message}");
throw;
}
finally { conn.Close(); }
}
public TaskInfo? QueryTaskInfo(string fileName, string url, long size, TaskState status)
{
string sql = $"SELECT * FROM t_tasks_info WHERE url = @url AND size = @size AND `status` = @status AND file_name = @fileName";
MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
try {
MySqlCommand sqlCmd = new MySqlCommand(sql, conn);
sqlCmd.Parameters.AddWithValue("@url", url);
sqlCmd.Parameters.AddWithValue("@size", size);
sqlCmd.Parameters.AddWithValue("@status", status);
sqlCmd.Parameters.AddWithValue("@fileName", fileName);
string result = QueryTableData(sqlCmd);
List<TaskInfo>? r = JsonConvert.DeserializeObject<List<TaskInfo>>(result);
if (r != null)
{
return r[0];
}
else
return null;
}
catch (Exception e){
return null;
}
finally {
conn.Close();
}
}
public bool InsertTaskData(TaskInfo taskInfo)
{
_logger.Debug(System.Text.Json.JsonSerializer.Serialize(taskInfo));
string sql = "INSERT INTO `t_tasks_info` (`tid`, `file_name`, `client_ip`, `add_time`, `update_time`, `status`, `url`, `size`, `hash`, `tag`) " +
"VALUES (@tid, @file_name, @client_ip, @add_time, @update_time, @status, @url, @size, @hash, @tag)";
MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
try
{
using MySqlCommand sqlCmd = new(sql, conn);
sqlCmd.Parameters.AddWithValue("@tid", taskInfo.TaskId);
sqlCmd.Parameters.AddWithValue("@file_name", taskInfo.FileName);
sqlCmd.Parameters.AddWithValue("@client_ip", taskInfo.ClientIp);
sqlCmd.Parameters.AddWithValue("@add_time", taskInfo.AddTime.ToString("yyyy-MM-dd HH:mm:ss"));
sqlCmd.Parameters.AddWithValue("@update_time", taskInfo.UpdateTime.ToString("yyyy-MM-dd HH:mm:ss"));
sqlCmd.Parameters.AddWithValue("@status", taskInfo.Status);
sqlCmd.Parameters.AddWithValue("@url", taskInfo.Url);
sqlCmd.Parameters.AddWithValue("@size", taskInfo.Size);
sqlCmd.Parameters.AddWithValue("@hash", taskInfo.Hash);
sqlCmd.Parameters.AddWithValue("@tag", taskInfo.Tag);
sqlCmd.ExecuteNonQuery();
}
catch (Exception)
{
_logger.Fatal($"插入数据时出现问题");
throw;
}
finally
{
conn.Close();
}
return true;
}
public bool UpdateFieldsData(string fieldsName, string key,string val)
{
string sql = $"UPDATE t_tasks_info set `{fieldsName}` = @Data WHERE `tid` = @tid";
MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
try
{
using MySqlCommand sqlCmd = new(sql, conn);
sqlCmd.Parameters.AddWithValue("@Data",val);
sqlCmd.Parameters.AddWithValue("@tid",key);
if (sqlCmd.ExecuteNonQuery() == 1)
{
return true;
}
else
return false;
}
catch (Exception)
{
_logger.Fatal($"Task Data update error.");
throw;
}
finally
{
conn.Close();
}
}
public bool UpdateTaskStatus(TaskInfo taskInfo)
{
string sql = @"UPDATE t_tasks_info set `status` = @status , update_time = Now() WHERE `tid` = @tid";
MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
try
{
using MySqlCommand sqlCmd = new (sql, conn);
sqlCmd.Parameters.AddWithValue("@status", taskInfo.Status);
sqlCmd.Parameters.AddWithValue("@tid", taskInfo.TaskId);
if (sqlCmd.ExecuteNonQuery() >= 1)
{
_logger.Debug($"Task: {taskInfo.TaskId} Status Change to {taskInfo.Status}");
return true;
}
else
_logger.Warning($"Task: {taskInfo.TaskId} Status Change Failed.");
return false;
}
catch (Exception)
{
_logger.Fatal($"Task status update error.");
throw;
}
finally
{
conn.Close ();
}
}
public bool UpdateTaskHash(TaskInfo taskInfo)
{
return UpdateFieldsData("hash", taskInfo.TaskId, MasterHelper.GetFileHash(Path.Combine(_appConfig.DownloadOptions.SavePath, taskInfo.FileName), FileHashAlgorithm.MD5));
}
public void TryInitialDB()
{
string sql = """
CREATE TABLE `t_tasks_info` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '',
`tid` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'id',
`file_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`client_ip` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'IP',
`add_time` datetime NOT NULL COMMENT '',
`update_time` datetime NOT NULL COMMENT '',
`status` int(11) NULL DEFAULT NULL COMMENT '',
`url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'url',
`size` int(11) NULL DEFAULT NULL COMMENT '',
`hash` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'hash',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
""";
MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
try
{
using MySqlCommand cmd = new(sql, conn);
cmd.ExecuteNonQuery();
}
catch (Exception)
{
_logger.Error($"Db Init Fai.l");
throw;
}
finally
{
conn.Close();
}
}
}
}