feat: 数据库备份增加压缩功能
This commit is contained in:
parent
cc6085f06d
commit
472fd5b753
@ -4,6 +4,7 @@
|
|||||||
//
|
//
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
using System.IO.Compression;
|
||||||
using DbType = SqlSugar.DbType;
|
using DbType = SqlSugar.DbType;
|
||||||
|
|
||||||
namespace Admin.NET.Core.Service;
|
namespace Admin.NET.Core.Service;
|
||||||
@ -176,7 +177,7 @@ public class SysDbBackupService : IDynamicApiController, ITransient
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 下载备份 🔖
|
/// 下载备份 🔖
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fileName"></param>
|
/// <param name="fileName">备份文件名</param>
|
||||||
[ApiDescriptionSettings(Name = "Download"), HttpGet]
|
[ApiDescriptionSettings(Name = "Download"), HttpGet]
|
||||||
[DisplayName("下载备份")]
|
[DisplayName("下载备份")]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
@ -187,4 +188,45 @@ public class SysDbBackupService : IDynamicApiController, ITransient
|
|||||||
var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||||
return new FileStreamResult(fs, "application/octet-stream") { FileDownloadName = fileName };
|
return new FileStreamResult(fs, "application/octet-stream") { FileDownloadName = fileName };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 压缩备份 🔖
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileName">备份文件名</param>
|
||||||
|
/// <returns>压缩后的文件路径</returns>
|
||||||
|
[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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -72,6 +72,54 @@ export const SysDbBackupApiAxiosParamCreator = function (configuration?: Configu
|
|||||||
options: localVarRequestOptions,
|
options: localVarRequestOptions,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @summary 压缩备份 🔖
|
||||||
|
* @param {string} [fileName] 备份文件名
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
apiSysDbBackupCompressPost: async (fileName?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||||
|
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 删除备份 🔖
|
* @summary 删除备份 🔖
|
||||||
@ -123,7 +171,7 @@ export const SysDbBackupApiAxiosParamCreator = function (configuration?: Configu
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @summary 下载备份 🔖
|
* @summary 下载备份 🔖
|
||||||
* @param {string} fileName
|
* @param {string} fileName 备份文件名
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
@ -235,6 +283,20 @@ export const SysDbBackupApiFp = function(configuration?: Configuration) {
|
|||||||
return axios.request(axiosRequestArgs);
|
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<AxiosResponse<void>>> {
|
||||||
|
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 删除备份 🔖
|
* @summary 删除备份 🔖
|
||||||
@ -252,7 +314,7 @@ export const SysDbBackupApiFp = function(configuration?: Configuration) {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @summary 下载备份 🔖
|
* @summary 下载备份 🔖
|
||||||
* @param {string} fileName
|
* @param {string} fileName 备份文件名
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
@ -295,6 +357,16 @@ export const SysDbBackupApiFactory = function (configuration?: Configuration, ba
|
|||||||
async apiSysDbBackupAddPost(configId?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
|
async apiSysDbBackupAddPost(configId?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
|
||||||
return SysDbBackupApiFp(configuration).apiSysDbBackupAddPost(configId, options).then((request) => request(axios, basePath));
|
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<AxiosResponse<void>> {
|
||||||
|
return SysDbBackupApiFp(configuration).apiSysDbBackupCompressPost(fileName, options).then((request) => request(axios, basePath));
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @summary 删除备份 🔖
|
* @summary 删除备份 🔖
|
||||||
@ -308,7 +380,7 @@ export const SysDbBackupApiFactory = function (configuration?: Configuration, ba
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @summary 下载备份 🔖
|
* @summary 下载备份 🔖
|
||||||
* @param {string} fileName
|
* @param {string} fileName 备份文件名
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
@ -345,6 +417,17 @@ export class SysDbBackupApi extends BaseAPI {
|
|||||||
public async apiSysDbBackupAddPost(configId?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
|
public async apiSysDbBackupAddPost(configId?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
|
||||||
return SysDbBackupApiFp(this.configuration).apiSysDbBackupAddPost(configId, options).then((request) => request(this.axios, this.basePath));
|
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<AxiosResponse<void>> {
|
||||||
|
return SysDbBackupApiFp(this.configuration).apiSysDbBackupCompressPost(fileName, options).then((request) => request(this.axios, this.basePath));
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @summary 删除备份 🔖
|
* @summary 删除备份 🔖
|
||||||
@ -359,7 +442,7 @@ export class SysDbBackupApi extends BaseAPI {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @summary 下载备份 🔖
|
* @summary 下载备份 🔖
|
||||||
* @param {string} fileName
|
* @param {string} fileName 备份文件名
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
* @memberof SysDbBackupApi
|
* @memberof SysDbBackupApi
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #row_buttons="{ row }">
|
<template #row_buttons="{ row }">
|
||||||
<el-button icon="ele-Delete" text type="danger" v-auth="'dbBackup/delete'" @click="handleDelete(row)"> 删除 </el-button>
|
<el-button icon="ele-Delete" text type="danger" v-auth="'dbBackup/delete'" @click="handleDelete(row)"> 删除 </el-button>
|
||||||
|
<el-button icon="ele-Files" text type="primary" @click="handleCompress(row)" v-if="!row.fileName.endsWith('.zip')"> 压缩 </el-button>
|
||||||
<el-button icon="ele-Download" text type="primary" @click="handleDownload(row)"> 下载 </el-button>
|
<el-button icon="ele-Download" text type="primary" @click="handleDownload(row)"> 下载 </el-button>
|
||||||
</template>
|
</template>
|
||||||
</vxe-grid>
|
</vxe-grid>
|
||||||
@ -63,7 +64,7 @@ const options = useVxeTable(
|
|||||||
{ field: 'fileName', title: '文件名称', minWidth: 200, showOverflow: 'tooltip' },
|
{ field: 'fileName', title: '文件名称', minWidth: 200, showOverflow: 'tooltip' },
|
||||||
{ field: 'size', title: '文件大小', width: 150, showOverflow: 'tooltip', slots: { default: 'row_size' } },
|
{ field: 'size', title: '文件大小', width: 150, showOverflow: 'tooltip', slots: { default: 'row_size' } },
|
||||||
{ field: 'createTime', title: '备份时间', width: 200, showOverflow: 'tooltip', slots: { default: 'row_createTime' } },
|
{ 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();
|
tempLink.click();
|
||||||
document.body.removeChild(tempLink);
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user