diff --git a/Admin.NET/Admin.NET.Core/Service/DataBase/SysDbBackupService.cs b/Admin.NET/Admin.NET.Core/Service/DataBase/SysDbBackupService.cs index af5d0e5e..33201621 100644 --- a/Admin.NET/Admin.NET.Core/Service/DataBase/SysDbBackupService.cs +++ b/Admin.NET/Admin.NET.Core/Service/DataBase/SysDbBackupService.cs @@ -4,6 +4,7 @@ // // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! +using System.IO.Compression; using DbType = SqlSugar.DbType; namespace Admin.NET.Core.Service; @@ -176,7 +177,7 @@ public class SysDbBackupService : IDynamicApiController, ITransient /// /// 下载备份 🔖 /// - /// + /// 备份文件名 [ApiDescriptionSettings(Name = "Download"), HttpGet] [DisplayName("下载备份")] [AllowAnonymous] @@ -187,4 +188,45 @@ public class SysDbBackupService : IDynamicApiController, ITransient var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); return new FileStreamResult(fs, "application/octet-stream") { FileDownloadName = fileName }; } + + /// + /// 压缩备份 🔖 + /// + /// 备份文件名 + /// 压缩后的文件路径 + [ApiDescriptionSettings(Name = "Compress"), HttpPost] + [DisplayName("压缩备份文件")] + public async Task Compress([FromQuery] string fileName) + { + var sourcePath = Path.Combine(_backupDir, fileName); + if (!File.Exists(sourcePath)) return; + + // 生成临时文件路径 + var tempPath = Path.Combine(Path.GetTempPath(), $"{Path.GetFileNameWithoutExtension(fileName)}.zip"); + var finalPath = Path.Combine(_backupDir, $"{Path.GetFileNameWithoutExtension(fileName)}.zip"); + + try + { + // 使用临时路径进行压缩 + await Task.Run(() => + { + using var zip = new ZipArchive(new FileStream(tempPath, FileMode.Create), ZipArchiveMode.Create); + var entry = zip.CreateEntry(fileName); + using var entryStream = entry.Open(); + using var fileStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read); + fileStream.CopyTo(entryStream); + }); + + // 压缩成功后,将临时文件移动到目标路径 + File.Move(tempPath, finalPath); + } + catch (Exception ex) + { + // 清理临时文件 + if (File.Exists(tempPath)) + File.Delete(tempPath); + + throw; + } + } } \ No newline at end of file diff --git a/Web/src/api-services/apis/sys-db-backup-api.ts b/Web/src/api-services/apis/sys-db-backup-api.ts index dcee4d19..ab253ae9 100644 --- a/Web/src/api-services/apis/sys-db-backup-api.ts +++ b/Web/src/api-services/apis/sys-db-backup-api.ts @@ -72,6 +72,54 @@ export const SysDbBackupApiAxiosParamCreator = function (configuration?: Configu options: localVarRequestOptions, }; }, + /** + * + * @summary 压缩备份 🔖 + * @param {string} [fileName] 备份文件名 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysDbBackupCompressPost: async (fileName?: string, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysDbBackup/compress`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + if (fileName !== undefined) { + localVarQueryParameter['fileName'] = fileName; + } + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, /** * * @summary 删除备份 🔖 @@ -123,7 +171,7 @@ export const SysDbBackupApiAxiosParamCreator = function (configuration?: Configu /** * * @summary 下载备份 🔖 - * @param {string} fileName + * @param {string} fileName 备份文件名 * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -235,6 +283,20 @@ export const SysDbBackupApiFp = function(configuration?: Configuration) { return axios.request(axiosRequestArgs); }; }, + /** + * + * @summary 压缩备份 🔖 + * @param {string} [fileName] 备份文件名 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysDbBackupCompressPost(fileName?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysDbBackupApiAxiosParamCreator(configuration).apiSysDbBackupCompressPost(fileName, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, /** * * @summary 删除备份 🔖 @@ -252,7 +314,7 @@ export const SysDbBackupApiFp = function(configuration?: Configuration) { /** * * @summary 下载备份 🔖 - * @param {string} fileName + * @param {string} fileName 备份文件名 * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -295,6 +357,16 @@ export const SysDbBackupApiFactory = function (configuration?: Configuration, ba async apiSysDbBackupAddPost(configId?: string, options?: AxiosRequestConfig): Promise> { return SysDbBackupApiFp(configuration).apiSysDbBackupAddPost(configId, options).then((request) => request(axios, basePath)); }, + /** + * + * @summary 压缩备份 🔖 + * @param {string} [fileName] 备份文件名 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysDbBackupCompressPost(fileName?: string, options?: AxiosRequestConfig): Promise> { + return SysDbBackupApiFp(configuration).apiSysDbBackupCompressPost(fileName, options).then((request) => request(axios, basePath)); + }, /** * * @summary 删除备份 🔖 @@ -308,7 +380,7 @@ export const SysDbBackupApiFactory = function (configuration?: Configuration, ba /** * * @summary 下载备份 🔖 - * @param {string} fileName + * @param {string} fileName 备份文件名 * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -345,6 +417,17 @@ export class SysDbBackupApi extends BaseAPI { public async apiSysDbBackupAddPost(configId?: string, options?: AxiosRequestConfig) : Promise> { return SysDbBackupApiFp(this.configuration).apiSysDbBackupAddPost(configId, options).then((request) => request(this.axios, this.basePath)); } + /** + * + * @summary 压缩备份 🔖 + * @param {string} [fileName] 备份文件名 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysDbBackupApi + */ + public async apiSysDbBackupCompressPost(fileName?: string, options?: AxiosRequestConfig) : Promise> { + return SysDbBackupApiFp(this.configuration).apiSysDbBackupCompressPost(fileName, options).then((request) => request(this.axios, this.basePath)); + } /** * * @summary 删除备份 🔖 @@ -359,7 +442,7 @@ export class SysDbBackupApi extends BaseAPI { /** * * @summary 下载备份 🔖 - * @param {string} fileName + * @param {string} fileName 备份文件名 * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof SysDbBackupApi diff --git a/Web/src/views/system/database/dbBackup.vue b/Web/src/views/system/database/dbBackup.vue index e52b5c9b..5ffd17cf 100644 --- a/Web/src/views/system/database/dbBackup.vue +++ b/Web/src/views/system/database/dbBackup.vue @@ -28,6 +28,7 @@ @@ -63,7 +64,7 @@ const options = useVxeTable( { field: 'fileName', title: '文件名称', minWidth: 200, showOverflow: 'tooltip' }, { field: 'size', title: '文件大小', width: 150, showOverflow: 'tooltip', slots: { default: 'row_size' } }, { field: 'createTime', title: '备份时间', width: 200, showOverflow: 'tooltip', slots: { default: 'row_createTime' } }, - { field: 'buttons', title: '操作', fixed: 'right', width: 150, showOverflow: true, slots: { default: 'row_buttons' } }, + { field: 'buttons', title: '操作', fixed: 'right', width: 200, showOverflow: true, slots: { default: 'row_buttons' } }, ], }, { @@ -145,6 +146,23 @@ const handleDownload = (row: any) => { tempLink.click(); document.body.removeChild(tempLink); }; + +// 压缩备份 +const handleCompress = async (row: any) => { + try { + await ElMessageBox.confirm(`确定要压缩备份:【${row.fileName}】吗?`, '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'info', + }); + + state.loading = true; + await getAPI(SysDbBackupApi).apiSysDbBackupCompressPost(row.fileName, { timeout: 0 /**永不超时 */ }); + await xGrid.value?.commitProxy('reload'); + } finally { + state.loading = false; + } +};