diff --git a/backend/app/api/v1/file.go b/backend/app/api/v1/file.go index 040d69627..c16f64c3a 100644 --- a/backend/app/api/v1/file.go +++ b/backend/app/api/v1/file.go @@ -34,3 +34,17 @@ func (b *BaseApi) GetFileTree(c *gin.Context) { } helper.SuccessWithData(c, tree) } + +func (b *BaseApi) CreateFile(c *gin.Context) { + var req dto.FileCreate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + err := fileService.Create(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} diff --git a/backend/app/dto/file.go b/backend/app/dto/file.go index 72bc876f1..2cd7b3d4b 100644 --- a/backend/app/dto/file.go +++ b/backend/app/dto/file.go @@ -1,6 +1,8 @@ package dto -import "github.com/1Panel-dev/1Panel/utils/files" +import ( + "github.com/1Panel-dev/1Panel/utils/files" +) type FileOption struct { files.FileOption @@ -16,3 +18,10 @@ type FileTree struct { Path string `json:"path"` Children []FileTree `json:"children"` } + +type FileCreate struct { + Path string + Content string + IsDir bool + Mode int64 +} diff --git a/backend/app/service/file.go b/backend/app/service/file.go index 3f850a3e6..f15d6530b 100644 --- a/backend/app/service/file.go +++ b/backend/app/service/file.go @@ -6,19 +6,12 @@ import ( "github.com/1Panel-dev/1Panel/app/dto" "github.com/1Panel-dev/1Panel/utils/files" "io" + "io/fs" ) type FileService struct { } -type IFileService interface { - GetFileList(op dto.FileOption) (dto.FileInfo, error) -} - -func NewFileService() IFileService { - return FileService{} -} - func (f FileService) GetFileList(op dto.FileOption) (dto.FileInfo, error) { var fileInfo dto.FileInfo info, err := files.NewFileInfo(op.FileOption) @@ -52,6 +45,16 @@ func (f FileService) GetFileTree(op dto.FileOption) ([]dto.FileTree, error) { return append(treeArray, node), nil } +func (f FileService) Create(op dto.FileCreate) error { + + fo := files.NewFileOp() + if op.IsDir { + return fo.CreateDir(op.Path, fs.FileMode(op.Mode)) + } + + return nil +} + func getUuid() string { b := make([]byte, 16) io.ReadFull(rand.Reader, b) diff --git a/backend/init/cache/cache.go b/backend/init/cache/cache.go index aff203ff8..e7f424ba3 100644 --- a/backend/init/cache/cache.go +++ b/backend/init/cache/cache.go @@ -1,18 +1,75 @@ package cache import ( + "fmt" "github.com/1Panel-dev/1Panel/global" "github.com/1Panel-dev/1Panel/init/cache/badger_db" "github.com/dgraph-io/badger/v3" + "time" ) func Init() { c := global.CONF.Cache - cache, err := badger.Open(badger.DefaultOptions(c.Path)) + options := badger.Options{ + Dir: c.Path, + ValueDir: c.Path, + ValueLogFileSize: 102400000, + ValueLogMaxEntries: 100000, + VLogPercentile: 0.1, + + MemTableSize: 64 << 20, + BaseTableSize: 2 << 20, + BaseLevelSize: 10 << 20, + TableSizeMultiplier: 2, + LevelSizeMultiplier: 10, + MaxLevels: 7, + NumGoroutines: 8, + MetricsEnabled: true, + NumCompactors: 4, + NumLevelZeroTables: 5, + NumLevelZeroTablesStall: 15, + NumMemtables: 5, + BloomFalsePositive: 0.01, + BlockSize: 4 * 1024, + SyncWrites: false, + NumVersionsToKeep: 1, + CompactL0OnClose: false, + VerifyValueChecksum: false, + BlockCacheSize: 256 << 20, + IndexCacheSize: 0, + ZSTDCompressionLevel: 1, + EncryptionKey: []byte{}, + EncryptionKeyRotationDuration: 10 * 24 * time.Hour, // Default 10 days. + DetectConflicts: true, + NamespaceOffset: -1, + } + + cache, err := badger.Open(options) if err != nil { panic(err) } global.CACHE = badger_db.NewCacheDB(cache) + + err = cache.View(func(txn *badger.Txn) error { + opts := badger.DefaultIteratorOptions + opts.PrefetchValues = false + it := txn.NewIterator(opts) + defer it.Close() + for it.Rewind(); it.Valid(); it.Next() { + item := it.Item() + k := item.Key() + fmt.Printf("key=%s\n", k) + } + return nil + }) + if err != nil { + panic(err) + } + fmt.Printf("run gc") + err = cache.RunValueLogGC(0.01) + if err != nil { + fmt.Printf(err.Error()) + } } diff --git a/backend/router/ro_file.go b/backend/router/ro_file.go index 447fd3894..27ea97518 100644 --- a/backend/router/ro_file.go +++ b/backend/router/ro_file.go @@ -17,6 +17,7 @@ func (f *FileRouter) InitFileRouter(Router *gin.RouterGroup) { { fileRouter.POST("/search", baseApi.ListFiles) fileRouter.POST("/tree", baseApi.GetFileTree) + fileRouter.POST("", baseApi.CreateFile) } } diff --git a/backend/utils/files/file_op.go b/backend/utils/files/file_op.go new file mode 100644 index 000000000..4d743a5ec --- /dev/null +++ b/backend/utils/files/file_op.go @@ -0,0 +1,44 @@ +package files + +import ( + "github.com/spf13/afero" + "io" + "io/fs" + "os" + "path" +) + +type FileOp struct { + Fs afero.Fs +} + +func NewFileOp() FileOp { + return FileOp{ + Fs: afero.NewOsFs(), + } +} + +func (f FileOp) CreateDir(dst string, mode fs.FileMode) error { + return f.Fs.MkdirAll(dst, mode) +} + +func (f FileOp) WriteFile(dst string, in io.Reader, mode fs.FileMode) error { + dir, _ := path.Split(dst) + if err := f.Fs.MkdirAll(dir, mode); err != nil { + return err + } + file, err := f.Fs.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode) + if err != nil { + return err + } + defer file.Close() + + if _, err = io.Copy(file, in); err != nil { + return err + } + + if _, err = file.Stat(); err != nil { + return err + } + return nil +} diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index 1b8882ffc..72ecf6222 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -1,6 +1,4 @@ import axios, { AxiosInstance, AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'; -// import { showFullScreenLoading, tryHideFullScreenLoading } from '@/config/service-loading'; -import { AxiosCanceler } from './helper/axios-cancel'; import { ResultData } from '@/api/interface'; import { ResultEnum } from '@/enums/http-enum'; import { checkStatus } from './helper/check-status'; @@ -9,7 +7,6 @@ import router from '@/routers'; import { GlobalStore } from '@/store'; const globalStore = GlobalStore(); -const axiosCanceler = new AxiosCanceler(); const config = { baseURL: import.meta.env.VITE_API_URL as string, @@ -30,8 +27,7 @@ class RequestHttp { ...config.headers, }; } - axiosCanceler.addPending(config); - // config.headers!.noLoading || showFullScreenLoading(); + return { ...config, }; @@ -43,12 +39,10 @@ class RequestHttp { this.service.interceptors.response.use( (response: AxiosResponse) => { - const { data, config } = response; + const { data } = response; if (response.headers['x-csrf-token']) { globalStore.setCsrfToken(response.headers['x-csrf-token']); } - axiosCanceler.removePending(config); - // tryHideFullScreenLoading(); if (data.code == ResultEnum.OVERDUE || data.code == ResultEnum.FORBIDDEN) { ElMessage.error(data.msg); router.replace({ @@ -64,7 +58,6 @@ class RequestHttp { }, async (error: AxiosError) => { const { response } = error; - // tryHideFullScreenLoading(); if (error.message.indexOf('timeout') !== -1) ElMessage.error('请求超时!请您稍后重试'); if (response) checkStatus(response.status); if (!window.navigator.onLine) router.replace({ path: '/500' }); diff --git a/frontend/src/api/interface/file.ts b/frontend/src/api/interface/file.ts index 012513fa6..89f6cfae6 100644 --- a/frontend/src/api/interface/file.ts +++ b/frontend/src/api/interface/file.ts @@ -29,4 +29,10 @@ export namespace File { path: string; children?: FileTree[]; } + + export interface FileCreate { + path: string; + isDir: Boolean; + mode: number; + } } diff --git a/frontend/src/api/modules/files.ts b/frontend/src/api/modules/files.ts index 38062f08c..357140f5b 100644 --- a/frontend/src/api/modules/files.ts +++ b/frontend/src/api/modules/files.ts @@ -8,3 +8,7 @@ export const GetFilesList = (params: File.ReqFile) => { export const GetFilesTree = (params: File.ReqFile) => { return http.post('files/tree', params); }; + +export const CreateFile = (form: File.FileCreate) => { + return http.post('files', form); +}; diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 9d82f921d..0ba405c2c 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -176,5 +176,6 @@ export default { zip: '压缩', user: '用户', group: '组', + path: '路径', }, }; diff --git a/frontend/src/views/file-management/create.vue b/frontend/src/views/file-management/create.vue new file mode 100644 index 000000000..282cf9864 --- /dev/null +++ b/frontend/src/views/file-management/create.vue @@ -0,0 +1,70 @@ + + + diff --git a/frontend/src/views/file-management/index.vue b/frontend/src/views/file-management/index.vue index 33de381c7..50f141dc1 100644 --- a/frontend/src/views/file-management/index.vue +++ b/frontend/src/views/file-management/index.vue @@ -43,17 +43,17 @@ v-loading="loading" >