// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 // // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 // // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! using DbType = SqlSugar.DbType; namespace Admin.NET.Core.Service; /// /// 系统数据库备份服务 🧩 /// [ApiDescriptionSettings(Order = 255, Description = "数据库备份")] public class SysDbBackupService : IDynamicApiController, ITransient { private readonly ISqlSugarClient _db; private readonly string _backupDir; private readonly SysDatabaseService _databaseService; public SysDbBackupService(ISqlSugarClient db, SysDatabaseService databaseService) { _db = db; _databaseService = databaseService; _backupDir = Path.Combine(App.WebHostEnvironment.WebRootPath, "DbBackup"); } /// /// 获取备份列表 🔖 /// /// [DisplayName("获取备份列表")] public List GetList() { try { if (!Directory.Exists(_backupDir)) Directory.CreateDirectory(_backupDir); var fileList = Directory.GetFiles(_backupDir); var dbBackupList = new List(); foreach (var item in fileList) { var info = new FileInfo(item); dbBackupList.Add(new DbBackupOutput { FileName = info.Name, Size = info.Length, CreateTime = info.CreationTime }); } return dbBackupList; } catch { return null; } } /// /// 备份数据库 🔖 /// /// [ApiDescriptionSettings(Name = "Add"), HttpPost] [DisplayName("备份数据库")] public async Task AddBackup([FromQuery] string configId) { await Backup(configId); } /// /// 删除备份 🔖 /// /// [ApiDescriptionSettings(Name = "Delete"), HttpPost] [DisplayName("删除备份")] public void DeleteBackup([FromQuery] string fileName) { var path = Path.Combine(_backupDir, fileName); File.Delete(path); } /// /// 备份数据库 /// /// [NonAction] public async Task Backup(string configId) { var options = App.GetOptions(); var option = options.ConnectionConfigs.FirstOrDefault(u => u.ConfigId + "" == configId) ?? throw Oops.Bah(ErrorCodeEnum.D1002); var db = _db.AsTenant().GetConnectionScope(configId); // 扩展名 var ext = "bak"; switch (option.DbType) { case DbType.MySql: ext = "sql"; break; case DbType.SqlServer: ext = "bak"; break; case DbType.Sqlite: ext = "db"; break; case DbType.PostgreSQL: ext = "sql"; break; } var path = Path.Combine(_backupDir, $"{db.Ado.Connection.Database}_{DateTime.Now:yyyyMMddHHmmss}.{ext}"); // 备份数据库 switch (option.DbType) { case DbType.MySql or DbType.Sqlite or DbType.SqlServer: await Task.Run(() => { db.DbMaintenance.BackupDataBase(db.Ado.Connection.Database, path); }); break; case DbType.PostgreSQL: { var fileStreamResult = (FileStreamResult)(await _databaseService.BackupDatabase()); // 将 fileStreamResult 保存为文件 await using var fileStream = new FileStream(path, FileMode.Create); await fileStreamResult.FileStream.CopyToAsync(fileStream); await fileStream.FlushAsync(); break; } default: throw Oops.Bah(ErrorCodeEnum.db1004, option.DbType); } } /// /// 删除过期备份文件 /// /// 过期天数 [NonAction] public void DeleteExpiredDbFile(int day = 7) { var list = Directory.GetFiles(_backupDir); foreach (var item in list) { var info = new FileInfo(item); if (info.CreationTime.AddDays(day) < DateTime.Now) { try { File.Delete(item); } catch (Exception) { // ignored } } } } }