mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-12-25 00:56:35 +08:00
feat: 新增linux文件夹创建&删除&其他优化
This commit is contained in:
@@ -44,7 +44,9 @@ export default defineComponent({
|
|||||||
state.isShowSearch = true;
|
state.isShowSearch = true;
|
||||||
initTageView();
|
initTageView();
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
layoutMenuAutocompleteRef.value.focus();
|
setTimeout(() => {
|
||||||
|
layoutMenuAutocompleteRef.value.focus();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
// 搜索弹窗关闭
|
// 搜索弹窗关闭
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
search();
|
search();
|
||||||
state.projects = (await projectApi.projects.request({ pageNum: 1, pageSize: 100 })).list;
|
state.projects = await projectApi.accountProjects.request(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
const choose = (item: any) => {
|
const choose = (item: any) => {
|
||||||
|
|||||||
@@ -135,7 +135,9 @@ export default defineComponent({
|
|||||||
state.db = props.db;
|
state.db = props.db;
|
||||||
state.dialogVisible = true;
|
state.dialogVisible = true;
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
remarkInputRef.value?.focus();
|
setTimeout(() => {
|
||||||
|
remarkInputRef.value?.focus();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,12 @@
|
|||||||
<el-link type="info" icon="view" :underline="false">查看</el-link>
|
<el-link type="info" icon="view" :underline="false">查看</el-link>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
|
|
||||||
|
<span v-auth="'machine:file:write'">
|
||||||
|
<el-dropdown-item @click="showCreateFileDialog(node, data)" v-if="data.type == 'd'">
|
||||||
|
<el-link type="primary" icon="document" :underline="false" style="margin-left: 2px">新建</el-link>
|
||||||
|
</el-dropdown-item>
|
||||||
|
</span>
|
||||||
|
|
||||||
<span v-auth="'machine:file:upload'">
|
<span v-auth="'machine:file:upload'">
|
||||||
<el-dropdown-item v-if="data.type == 'd'">
|
<el-dropdown-item v-if="data.type == 'd'">
|
||||||
<el-upload
|
<el-upload
|
||||||
@@ -133,6 +139,35 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
:destroy-on-close="true"
|
||||||
|
title="新建文件"
|
||||||
|
v-model="createFileDialog.visible"
|
||||||
|
:before-close="closeCreateFileDialog"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
top="5vh"
|
||||||
|
width="400px"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<el-form-item prop="name" label="名称:">
|
||||||
|
<el-input v-model.trim="createFileDialog.name" placeholder="请输入名称" auto-complete="off"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="type" label="类型:">
|
||||||
|
<el-radio-group v-model="createFileDialog.type">
|
||||||
|
<el-radio label="d" size="small">文件夹</el-radio>
|
||||||
|
<el-radio label="-" size="small">文件</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="closeCreateFileDialog">关闭</el-button>
|
||||||
|
<el-button v-auth="'machine:file:write'" type="primary" @click="createFile">确定</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
:destroy-on-close="true"
|
:destroy-on-close="true"
|
||||||
:title="fileContent.dialogTitle"
|
:title="fileContent.dialogTitle"
|
||||||
@@ -164,6 +199,7 @@ import { codemirror } from '@/components/codemirror';
|
|||||||
import { getSession } from '@/common/utils/storage';
|
import { getSession } from '@/common/utils/storage';
|
||||||
import enums from './enums';
|
import enums from './enums';
|
||||||
import config from '@/common/config';
|
import config from '@/common/config';
|
||||||
|
import { isTrue } from '@/common/assert';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'FileManage',
|
name: 'FileManage',
|
||||||
@@ -184,26 +220,8 @@ export default defineComponent({
|
|||||||
const fileTree: any = ref(null);
|
const fileTree: any = ref(null);
|
||||||
const token = getSession('token');
|
const token = getSession('token');
|
||||||
|
|
||||||
const cmOptions = {
|
const folderType = 'd';
|
||||||
tabSize: 2,
|
const fileType = '-';
|
||||||
mode: 'text/x-sh',
|
|
||||||
theme: 'panda-syntax',
|
|
||||||
line: true,
|
|
||||||
// 开启校验
|
|
||||||
lint: true,
|
|
||||||
gutters: ['CodeMirror-lint-markers'],
|
|
||||||
indentWithTabs: true,
|
|
||||||
smartIndent: true,
|
|
||||||
matchBrackets: true,
|
|
||||||
autofocus: true,
|
|
||||||
styleSelectedText: true,
|
|
||||||
styleActiveLine: true, // 高亮选中行
|
|
||||||
foldGutter: true, // 块槽
|
|
||||||
hintOptions: {
|
|
||||||
// 当匹配只有一项的时候是否自动补全
|
|
||||||
completeSingle: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
@@ -250,6 +268,12 @@ export default defineComponent({
|
|||||||
path: '',
|
path: '',
|
||||||
type: '',
|
type: '',
|
||||||
},
|
},
|
||||||
|
createFileDialog: {
|
||||||
|
visible: false,
|
||||||
|
name: '',
|
||||||
|
type: folderType,
|
||||||
|
node: null as any,
|
||||||
|
},
|
||||||
file: null as any,
|
file: null as any,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -272,18 +296,6 @@ export default defineComponent({
|
|||||||
getFiles();
|
getFiles();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* tab切换触发事件
|
|
||||||
* @param {Object} tab
|
|
||||||
* @param {Object} event
|
|
||||||
*/
|
|
||||||
// handleClick(tab, event) {
|
|
||||||
// // if (tab.name == 'file-manage') {
|
|
||||||
// // this.fileManage.node.childNodes = [];
|
|
||||||
// // this.loadNode(this.fileManage.node, this.fileManage.resolve);
|
|
||||||
// // }
|
|
||||||
// }
|
|
||||||
|
|
||||||
const add = () => {
|
const add = () => {
|
||||||
// 往数组头部添加元素
|
// 往数组头部添加元素
|
||||||
state.fileTable = [{}].concat(state.fileTable);
|
state.fileTable = [{}].concat(state.fileTable);
|
||||||
@@ -311,7 +323,6 @@ export default defineComponent({
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
getFiles();
|
getFiles();
|
||||||
// state.fileTable.splice(idx, 1);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -388,7 +399,6 @@ export default defineComponent({
|
|||||||
emit('update:visible', false);
|
emit('update:visible', false);
|
||||||
emit('update:machineId', null);
|
emit('update:machineId', null);
|
||||||
emit('cancel');
|
emit('cancel');
|
||||||
// state.activeName = 'conf-file'
|
|
||||||
state.fileTable = [];
|
state.fileTable = [];
|
||||||
state.tree.folder = { id: 0 };
|
state.tree.folder = { id: 0 };
|
||||||
};
|
};
|
||||||
@@ -413,7 +423,7 @@ export default defineComponent({
|
|||||||
return resolve([
|
return resolve([
|
||||||
{
|
{
|
||||||
name: path,
|
name: path,
|
||||||
type: 'd',
|
type: folderType,
|
||||||
path: path,
|
path: path,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@@ -435,13 +445,42 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
for (const file of res) {
|
for (const file of res) {
|
||||||
const type = file.type;
|
const type = file.type;
|
||||||
if (type != 'd') {
|
if (type == fileType) {
|
||||||
file.leaf = true;
|
file.leaf = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return resolve(res);
|
return resolve(res);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showCreateFileDialog = (node: any) => {
|
||||||
|
isTrue(node.expanded, '请先点击展开该节点后再创建');
|
||||||
|
state.createFileDialog.node = node;
|
||||||
|
state.createFileDialog.visible = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFile = async () => {
|
||||||
|
const node = state.createFileDialog.node;
|
||||||
|
console.log(node.data);
|
||||||
|
const name = state.createFileDialog.name;
|
||||||
|
const type = state.createFileDialog.type;
|
||||||
|
const path = node.data.path + '/' + name;
|
||||||
|
await machineApi.createFile.request({
|
||||||
|
machineId: props.machineId,
|
||||||
|
id: state.tree.folder.id,
|
||||||
|
path,
|
||||||
|
type,
|
||||||
|
});
|
||||||
|
fileTree.value.append({ name: name, path: path, type: type, leaf: type === fileType, size: 0 }, node);
|
||||||
|
closeCreateFileDialog();
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeCreateFileDialog = () => {
|
||||||
|
state.createFileDialog.visible = false;
|
||||||
|
state.createFileDialog.node = null;
|
||||||
|
state.createFileDialog.name = '';
|
||||||
|
state.createFileDialog.type = folderType;
|
||||||
|
};
|
||||||
|
|
||||||
const deleteFile = (node: any, data: any) => {
|
const deleteFile = (node: any, data: any) => {
|
||||||
const file = data.path;
|
const file = data.path;
|
||||||
ElMessageBox.confirm(`此操作将删除 [${file}], 是否继续?`, '提示', {
|
ElMessageBox.confirm(`此操作将删除 [${file}], 是否继续?`, '提示', {
|
||||||
@@ -468,7 +507,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
const downloadFile = (node: any, data: any) => {
|
const downloadFile = (node: any, data: any) => {
|
||||||
const a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
// a.setAttribute('target', '_blank')
|
|
||||||
a.setAttribute(
|
a.setAttribute(
|
||||||
'href',
|
'href',
|
||||||
`${config.baseApiUrl}/machines/${props.machineId}/files/${state.tree.folder.id}/read?type=1&path=${data.path}&token=${token}`
|
`${config.baseApiUrl}/machines/${props.machineId}/files/${state.tree.folder.id}/read?type=1&path=${data.path}&token=${token}`
|
||||||
@@ -516,7 +554,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
const beforeUpload = (file: File) => {
|
const beforeUpload = (file: File) => {
|
||||||
state.file = file;
|
state.file = file;
|
||||||
// ElMessage.success(`'${file.name}' 上传中,请关注结果通知`);
|
|
||||||
};
|
};
|
||||||
const getFilePath = (data: object, visible: boolean) => {
|
const getFilePath = (data: object, visible: boolean) => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
@@ -572,7 +609,6 @@ export default defineComponent({
|
|||||||
fileTree,
|
fileTree,
|
||||||
enums,
|
enums,
|
||||||
token,
|
token,
|
||||||
cmOptions,
|
|
||||||
add,
|
add,
|
||||||
getFiles,
|
getFiles,
|
||||||
handlePageChange,
|
handlePageChange,
|
||||||
@@ -583,6 +619,9 @@ export default defineComponent({
|
|||||||
updateContent,
|
updateContent,
|
||||||
handleClose,
|
handleClose,
|
||||||
loadNode,
|
loadNode,
|
||||||
|
showCreateFileDialog,
|
||||||
|
closeCreateFileDialog,
|
||||||
|
createFile,
|
||||||
deleteFile,
|
deleteFile,
|
||||||
downloadFile,
|
downloadFile,
|
||||||
getUploadFile,
|
getUploadFile,
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export const machineApi = {
|
|||||||
rmFile: Api.create("/machines/{machineId}/files/{fileId}/remove", 'delete'),
|
rmFile: Api.create("/machines/{machineId}/files/{fileId}/remove", 'delete'),
|
||||||
uploadFile: Api.create("/machines/{machineId}/files/{fileId}/upload?token={token}", 'post'),
|
uploadFile: Api.create("/machines/{machineId}/files/{fileId}/upload?token={token}", 'post'),
|
||||||
fileContent: Api.create("/machines/{machineId}/files/{fileId}/read", 'get'),
|
fileContent: Api.create("/machines/{machineId}/files/{fileId}/read", 'get'),
|
||||||
|
createFile: Api.create("/machines/{machineId}/files/{id}/create-file", 'post'),
|
||||||
// 修改文件内容
|
// 修改文件内容
|
||||||
updateFileContent: Api.create("/machines/{machineId}/files/{id}/write", 'post'),
|
updateFileContent: Api.create("/machines/{machineId}/files/{id}/write", 'post'),
|
||||||
// 添加文件or目录
|
// 添加文件or目录
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
search();
|
search();
|
||||||
state.projects = (await projectApi.projects.request({ pageNum: 1, pageSize: 100 })).list;
|
state.projects = await projectApi.accountProjects.request(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
const handlePageChange = (curPage: number) => {
|
const handlePageChange = (curPage: number) => {
|
||||||
@@ -266,12 +266,6 @@ export default defineComponent({
|
|||||||
state.currentData = item;
|
state.currentData = item;
|
||||||
};
|
};
|
||||||
|
|
||||||
// connect() {
|
|
||||||
// Req.post('/open/redis/connect', this.form, res => {
|
|
||||||
// this.redisInfo = res
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
const showDatabases = async (id: number) => {
|
const showDatabases = async (id: number) => {
|
||||||
state.databaseDialog.data = (await mongoApi.databases.request({ id })).Databases;
|
state.databaseDialog.data = (await mongoApi.databases.request({ id })).Databases;
|
||||||
state.databaseDialog.title = `数据库列表`;
|
state.databaseDialog.title = `数据库列表`;
|
||||||
@@ -371,14 +365,6 @@ export default defineComponent({
|
|||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// const info = (redis: any) => {
|
|
||||||
// redisApi.redisInfo.request({ id: redis.id }).then((res: any) => {
|
|
||||||
// state.infoDialog.info = res;
|
|
||||||
// state.infoDialog.title = `'${redis.host}' info`;
|
|
||||||
// state.infoDialog.visible = true;
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
|
|
||||||
const search = async () => {
|
const search = async () => {
|
||||||
const res = await mongoApi.mongoList.request(state.query);
|
const res = await mongoApi.mongoList.request(state.query);
|
||||||
state.list = res.list;
|
state.list = res.list;
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
search();
|
search();
|
||||||
state.projects = (await projectApi.projects.request({ pageNum: 1, pageSize: 100 })).list;
|
state.projects = await projectApi.accountProjects.request(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
const handlePageChange = (curPage: number) => {
|
const handlePageChange = (curPage: number) => {
|
||||||
|
|||||||
@@ -15,6 +15,13 @@ type DbForm struct {
|
|||||||
EnvId uint64 `binding:"required" json:"envId"`
|
EnvId uint64 `binding:"required" json:"envId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DbSqlSaveForm struct {
|
||||||
|
Name string
|
||||||
|
Sql string `binding:"required"`
|
||||||
|
Type int `binding:"required"`
|
||||||
|
Db string `binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
// 数据库SQL执行表单
|
// 数据库SQL执行表单
|
||||||
type DbSqlExecForm struct {
|
type DbSqlExecForm struct {
|
||||||
Db string `binding:"required" json:"db"` //数据库名
|
Db string `binding:"required" json:"db"` //数据库名
|
||||||
|
|||||||
@@ -38,11 +38,9 @@ type MachineScriptForm struct {
|
|||||||
Script string `binding:"required"`
|
Script string `binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DbSqlSaveForm struct {
|
type MachineCreateFileForm struct {
|
||||||
Name string
|
Path string `binding:"required"`
|
||||||
Sql string `binding:"required"`
|
Type string `binding:"required"`
|
||||||
Type int `binding:"required"`
|
|
||||||
Db string `binding:"required"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type MachineFileUpdateForm struct {
|
type MachineFileUpdateForm struct {
|
||||||
@@ -60,6 +60,22 @@ func (m *MachineFile) DeleteFile(rc *ctx.ReqCtx) {
|
|||||||
|
|
||||||
/*** sftp相关操作 */
|
/*** sftp相关操作 */
|
||||||
|
|
||||||
|
func (m *MachineFile) CreateFile(rc *ctx.ReqCtx) {
|
||||||
|
g := rc.GinCtx
|
||||||
|
fid := GetMachineFileId(g)
|
||||||
|
|
||||||
|
form := new(form.MachineCreateFileForm)
|
||||||
|
ginx.BindJsonAndValid(g, form)
|
||||||
|
path := form.Path
|
||||||
|
|
||||||
|
if form.Type == dir {
|
||||||
|
m.MachineFileApp.MkDir(fid, form.Path)
|
||||||
|
} else {
|
||||||
|
m.MachineFileApp.CreateFile(fid, form.Path)
|
||||||
|
}
|
||||||
|
rc.ReqParam = fmt.Sprintf("path: %s, type: %s", path, form.Type)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *MachineFile) ReadFileContent(rc *ctx.ReqCtx) {
|
func (m *MachineFile) ReadFileContent(rc *ctx.ReqCtx) {
|
||||||
g := rc.GinCtx
|
g := rc.GinCtx
|
||||||
fid := GetMachineFileId(g)
|
fid := GetMachineFileId(g)
|
||||||
@@ -104,6 +120,7 @@ func (m *MachineFile) GetDirEntry(rc *ctx.ReqCtx) {
|
|||||||
Size: fi.Size(),
|
Size: fi.Size(),
|
||||||
Path: readPath + fi.Name(),
|
Path: readPath + fi.Name(),
|
||||||
Type: getFileType(fi.Mode()),
|
Type: getFileType(fi.Mode()),
|
||||||
|
Mode: fi.Mode().String(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
rc.ResData = fisVO
|
rc.ResData = fisVO
|
||||||
@@ -155,7 +172,6 @@ func (m *MachineFile) UploadFile(rc *ctx.ReqCtx) {
|
|||||||
func (m *MachineFile) RemoveFile(rc *ctx.ReqCtx) {
|
func (m *MachineFile) RemoveFile(rc *ctx.ReqCtx) {
|
||||||
g := rc.GinCtx
|
g := rc.GinCtx
|
||||||
fid := GetMachineFileId(g)
|
fid := GetMachineFileId(g)
|
||||||
// mid := GetMachineId(g)
|
|
||||||
path := g.Query("path")
|
path := g.Query("path")
|
||||||
|
|
||||||
m.MachineFileApp.RemoveFile(fid, path)
|
m.MachineFileApp.RemoveFile(fid, path)
|
||||||
@@ -167,7 +183,10 @@ func getFileType(fm fs.FileMode) string {
|
|||||||
if fm.IsDir() {
|
if fm.IsDir() {
|
||||||
return dir
|
return dir
|
||||||
}
|
}
|
||||||
return file
|
if fm.IsRegular() {
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
return dir
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMachineFileId(g *gin.Context) uint64 {
|
func GetMachineFileId(g *gin.Context) uint64 {
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ type MachineFileInfo struct {
|
|||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
Size int64 `json:"size"`
|
Size int64 `json:"size"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
Mode string `json:"mode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoleVO struct {
|
type RoleVO struct {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package application
|
package application
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"mayfly-go/internal/devops/domain/entity"
|
"mayfly-go/internal/devops/domain/entity"
|
||||||
@@ -30,6 +31,12 @@ type MachineFile interface {
|
|||||||
|
|
||||||
/** sftp 相关操作 **/
|
/** sftp 相关操作 **/
|
||||||
|
|
||||||
|
// 创建目录
|
||||||
|
MkDir(fid uint64, path string)
|
||||||
|
|
||||||
|
// 创建文件
|
||||||
|
CreateFile(fid uint64, path string)
|
||||||
|
|
||||||
// 读取目录
|
// 读取目录
|
||||||
ReadDir(fid uint64, path string) []fs.FileInfo
|
ReadDir(fid uint64, path string) []fs.FileInfo
|
||||||
|
|
||||||
@@ -100,6 +107,25 @@ func (m *machineFileAppImpl) ReadDir(fid uint64, path string) []fs.FileInfo {
|
|||||||
return fis
|
return fis
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *machineFileAppImpl) MkDir(fid uint64, path string) {
|
||||||
|
path, machineId := m.checkAndReturnPathMid(fid, path)
|
||||||
|
if !strings.HasSuffix(path, "/") {
|
||||||
|
path = path + "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
sftpCli := m.getSftpCli(machineId)
|
||||||
|
err := sftpCli.Mkdir(path)
|
||||||
|
biz.ErrIsNilAppendErr(err, "创建目录失败: %s")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *machineFileAppImpl) CreateFile(fid uint64, path string) {
|
||||||
|
path, machineId := m.checkAndReturnPathMid(fid, path)
|
||||||
|
sftpCli := m.getSftpCli(machineId)
|
||||||
|
file, err := sftpCli.Create(path)
|
||||||
|
biz.ErrIsNilAppendErr(err, "创建文件失败: %s")
|
||||||
|
defer file.Close()
|
||||||
|
}
|
||||||
|
|
||||||
func (m *machineFileAppImpl) ReadFile(fileId uint64, path string) *sftp.File {
|
func (m *machineFileAppImpl) ReadFile(fileId uint64, path string) *sftp.File {
|
||||||
path, machineId := m.checkAndReturnPathMid(fileId, path)
|
path, machineId := m.checkAndReturnPathMid(fileId, path)
|
||||||
sftpCli := m.getSftpCli(machineId)
|
sftpCli := m.getSftpCli(machineId)
|
||||||
@@ -148,6 +174,11 @@ func (m *machineFileAppImpl) RemoveFile(fileId uint64, path string) {
|
|||||||
fi, _ := file.Stat()
|
fi, _ := file.Stat()
|
||||||
if fi.IsDir() {
|
if fi.IsDir() {
|
||||||
err = sftpCli.RemoveDirectory(path)
|
err = sftpCli.RemoveDirectory(path)
|
||||||
|
// 如果文件夹有内容会删除失败,则使用rm -rf命令删除
|
||||||
|
if err != nil {
|
||||||
|
MachineApp.GetCli(machineId).Run(fmt.Sprintf("rm -rf %s", path))
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err = sftpCli.Remove(path)
|
err = sftpCli.Remove(path)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,14 +43,14 @@ func InitMachineFileRouter(router *gin.RouterGroup) {
|
|||||||
|
|
||||||
getContent := ctx.NewLogInfo("读取机器文件内容")
|
getContent := ctx.NewLogInfo("读取机器文件内容")
|
||||||
machineFile.GET(":machineId/files/:fileId/read", func(c *gin.Context) {
|
machineFile.GET(":machineId/files/:fileId/read", func(c *gin.Context) {
|
||||||
rc := ctx.NewReqCtxWithGin(c).WithLog(getContent)
|
ctx.NewReqCtxWithGin(c).WithLog(getContent).
|
||||||
rc.Handle(mf.ReadFileContent)
|
Handle(mf.ReadFileContent)
|
||||||
})
|
})
|
||||||
|
|
||||||
getDir := ctx.NewLogInfo("读取机器目录")
|
getDir := ctx.NewLogInfo("读取机器目录")
|
||||||
machineFile.GET(":machineId/files/:fileId/read-dir", func(c *gin.Context) {
|
machineFile.GET(":machineId/files/:fileId/read-dir", func(c *gin.Context) {
|
||||||
rc := ctx.NewReqCtxWithGin(c).WithLog(getDir)
|
ctx.NewReqCtxWithGin(c).WithLog(getDir).
|
||||||
rc.Handle(mf.GetDirEntry)
|
Handle(mf.GetDirEntry)
|
||||||
})
|
})
|
||||||
|
|
||||||
writeFile := ctx.NewLogInfo("写入or下载文件内容")
|
writeFile := ctx.NewLogInfo("写入or下载文件内容")
|
||||||
@@ -61,6 +61,13 @@ func InitMachineFileRouter(router *gin.RouterGroup) {
|
|||||||
Handle(mf.WriteFileContent)
|
Handle(mf.WriteFileContent)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
createFile := ctx.NewLogInfo("创建机器文件or目录")
|
||||||
|
machineFile.POST(":machineId/files/:fileId/create-file", func(c *gin.Context) {
|
||||||
|
ctx.NewReqCtxWithGin(c).WithLog(createFile).
|
||||||
|
WithRequiredPermission(wfP).
|
||||||
|
Handle(mf.CreateFile)
|
||||||
|
})
|
||||||
|
|
||||||
uploadFile := ctx.NewLogInfo("文件上传")
|
uploadFile := ctx.NewLogInfo("文件上传")
|
||||||
ufP := ctx.NewPermission("machine:file:upload")
|
ufP := ctx.NewPermission("machine:file:upload")
|
||||||
machineFile.POST(":machineId/files/:fileId/upload", func(c *gin.Context) {
|
machineFile.POST(":machineId/files/:fileId/upload", func(c *gin.Context) {
|
||||||
|
|||||||
Reference in New Issue
Block a user