零信任Web访问控制系统-备份

总体概览

前端

基本结构

  1. 系统备份暂存天数展示框。
  2. 修改/保存备份暂存天数的按钮。
  3. 设置备份文件名的输入框。
  4. 使用备份文件名备份文件的立即备份按钮。
  5. 通过备份时间与备份文件名搜索备份文件的高级搜索下拉框。
  6. 展示备份文件/备份文件名/操作的展示表格,操作列中包括下载备份与删除备份。

知识总结

  1. 表格内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<el-table :data="backupList" style="width: 100%">
<el-table-column label="备份时间">
<template slot-scope="scope">{{ scope.row.backup_create_time }}</template>
</el-table-column>
<el-table-column label="备份文件名">
<template slot-scope="scope">{{ scope.row.backup_file_name }}</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button
@click.native.prevent="downloadBackup(scope.row.backup_file_name)"
type="primary"
icon="el-icon-download"
size="small">
下载备份
</el-button>
<el-button
@click.native.prevent="deleteBackup(scope.row.backup_file_name)"
type="danger"
icon="el-icon-delete"
size="small">
删除备份
</el-button>
</template>
</el-table-column>
</el-table>

backupList表示整个表格对应的一整个列表[{},{},…,{}],scope.row表示每行对应元组中的元组信息。

  1. 前端接口类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 类型1
export function getBackupList(page, pageSize) {
return request({
url: '/url/get_backup_list?page=' + page + '&pageSize=' + pageSize,
method: 'get'
})
}

// 类型2
export function saveBackup(params) {
return request({
url: '/url/save_backup',
method: 'put',
data: params
})
}

目前使用的前端接口主要有上述两种类型,类型1较为直接,是通过直接给函数传入若干参数直接写死的;类型2比较灵活,可以使用将多个变量定义成一个json以params变量传入,实现相对简单。

  1. 下载文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
export const downloadBackup = (fileName) => {
return request({
url: '/url/download_backup',
method: 'get',
params: {
fileName: fileName
},
responseType: 'blob'
}).then((res) => {
handleFileError(res, fileName)
})
}

const handleFileError = (res, fileName) => {
if (typeof (res.data) !== 'undefined') {
if (res.data.type === 'application/json') {
const reader = new FileReader()
reader.onload = function() {
const message = JSON.parse(reader.result).msg
this.$message({
showClose: true,
message: message,
type: 'error'
})
}
reader.readAsText(new Blob([res.data]))
}
} else {
var downloadUrl = window.URL.createObjectURL(new Blob([res]))
var a = document.createElement('a')
a.style.display = 'none'
a.href = downloadUrl
a.download = fileName
var event = new MouseEvent('click')
a.dispatchEvent(event)
}
}

此处使用的是函数变量的方法。

  1. 实现表格翻页
1
2
3
4
5
6
7
8
9
10
11
<div align="center" style="padding-top: 20px">
<el-pagination
:current-page="currentPage"
:page-sizes="[10,20,30]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>

currentPage表示目前的页数,pageSize表示目前每页显示的数据条数,total表示总数据条数。

handleSizeChange(size)函数使用size表示选择每页能显示的数据条数,handleCurrentChange(currentPage)函数使用currentPage表示选择的页数。

后端

知识总结

  1. 读取某个文件夹中的文件并获取对应的创建时间,并按照创建时间排序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
backupList := make([]response.Backup, 0)
// 读取某个文件夹的对应内容
backupListTmp, err := ioutil.ReadDir("./backup")
if err != nil {
logrus.Error(err)
}
// 以下获取各个文件的创建时间
// 保存各个文件的实际路径
var backupUrlList []string
for _, v := range backupListTmp {
backupUrlList = append(backupUrlList, "./backup/"+v.Name())
}
for i := 0; i < len(backupUrlList); i++ {
finfo, _ := os.Stat(backupUrlList[i])
fileAttr := finfo.Sys().(*syscall.Stat_t)
backupTmp := new(response.Backup)
backupTmp.BackupCreateTime = SecondToTime(fileAttr.Ctimespec.Sec).Format("2006-01-02 15:04:05")
backupTmp.BackupFileName = backupListTmp[i].Name()
backupList = append(backupList, *backupTmp)
}
// 按照创建时间进行排序
loc, _ := time.LoadLocation("Local")
sort.Slice(backupList, func(i, j int) bool {
timeI, _ := time.ParseInLocation("2006-01-02 15:04:05", backupList[i].BackupCreateTime, loc)
timeJ, _ := time.ParseInLocation("2006-01-02 15:04:05", backupList[j].BackupCreateTime, loc)
return timeI.Before(timeJ)
})

// 把秒级的时间戳转为time格式
func SecondToTime(sec int64) time.Time {
return time.Unix(sec, 0)
}
  1. 定时任务。
1
2
cron.NewCron("定时任务名称", "@daily", funcName) // @daily表示每天0点执行 "0 0 8 * * ?"表示每天8点执行
cron.Start()

funcName表示需要定时执行的函数名,需要返回一个error类型的变量

  1. 删除文件
1
err := os.Remove(deleteFileUrl)
  1. 下载文件
1
2
3
4
5
6
7
8
9
10
11
12
13
func DownloadBackup(c *gin.Context) {
fileName := c.Query("fileName")
filePath := "./url/" + fileName
ok, err := utils.PathExists(filePath)
if !ok || err != nil {
global.ADS_LOG.Error("文件不存在!", zap.Any("err", err))
response.FailWithMessage("文件不存在", c)
return
}
c.Header("success", "true")
c.Header("content-type", "content-type-value")
c.File(filePath)
}