Feat: list objects in specific path

pull/247/head
HFO4 2019-11-24 13:06:15 +08:00
parent a89c3cb11a
commit b431f3674c
8 changed files with 144 additions and 15 deletions

View File

@ -31,6 +31,13 @@ func (file *File) Create() (uint, error) {
// GetFileByPathAndName 给定路径、文件名、用户ID查找文件 // GetFileByPathAndName 给定路径、文件名、用户ID查找文件
func GetFileByPathAndName(path string, name string, uid uint) (File, error) { func GetFileByPathAndName(path string, name string, uid uint) (File, error) {
var file File var file File
result := DB.Where("user_id = ? AND dir = ? AND name=?", uid, path, name).Find(&file) result := DB.Where("user_id = ? AND dir = ? AND name=?", uid, path, name).First(&file)
return file, result.Error return file, result.Error
} }
// GetChildFile 查找目录下子文件 TODO:test
func (folder *Folder) GetChildFile() ([]File, error) {
var files []File
result := DB.Where("folder_id = ?", folder.ID).Find(&files)
return files, result.Error
}

View File

@ -16,7 +16,7 @@ type Folder struct {
PositionAbsolute string `gorm:"size:65536"` PositionAbsolute string `gorm:"size:65536"`
} }
// Create 创建目录 // Create 创建目录 TODO:test
func (folder *Folder) Create() (uint, error) { func (folder *Folder) Create() (uint, error) {
if err := DB.Create(folder).Error; err != nil { if err := DB.Create(folder).Error; err != nil {
util.Log().Warning("无法插入目录记录, %s", err) util.Log().Warning("无法插入目录记录, %s", err)
@ -28,6 +28,13 @@ func (folder *Folder) Create() (uint, error) {
// GetFolderByPath 根据绝对路径和UID查找目录 // GetFolderByPath 根据绝对路径和UID查找目录
func GetFolderByPath(path string, uid uint) (Folder, error) { func GetFolderByPath(path string, uid uint) (Folder, error) {
var folder Folder var folder Folder
result := DB.Where("owner_id = ? AND position_absolute = ?", uid, path).Find(&folder) result := DB.Where("owner_id = ? AND position_absolute = ?", uid, path).First(&folder)
return folder, result.Error return folder, result.Error
} }
// GetChildFolder 查找子目录 TODO:test
func (folder *Folder) GetChildFolder() ([]Folder, error) {
var folders []Folder
result := DB.Where("parent_id = ?", folder.ID).Find(&folders)
return folders, result.Error
}

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"github.com/HFO4/cloudreve/models" "github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/filesystem/local" "github.com/HFO4/cloudreve/pkg/filesystem/local"
"github.com/gin-gonic/gin"
testMock "github.com/stretchr/testify/mock" testMock "github.com/stretchr/testify/mock"
"io" "io"
) )
@ -73,3 +74,11 @@ func NewFileSystem(user *model.User) (*FileSystem, error) {
Handler: handler, Handler: handler,
}, nil }, nil
} }
// NewFileSystemFromContext 从gin.Context创建文件系统
// TODO:test
func NewFileSystemFromContext(c *gin.Context) (*FileSystem, error) {
user, _ := c.Get("user")
fs, err := NewFileSystem(user.(*model.User))
return fs, err
}

View File

@ -11,7 +11,79 @@ import (
================= =================
*/ */
// CreateDirectory 在`base`路径下创建名为`dir`的目录 // Object 文件或者目录
type Object struct {
ID uint `json:"id"`
Name string `json:"name"`
Path string `json:"path"`
Pic string `json:"pic"`
Size uint64 `json:"size"`
Type string `json:"type"`
}
// List 列出路径下的内容
func (fs *FileSystem) List(ctx context.Context, path string, pathProcessor func(string) string) ([]Object, error) {
// 获取父目录
isExist, folder := fs.IsPathExist(path)
// 不存在时返回空的结果
if !isExist {
return nil, nil
}
// 获取子目录
childFolders, _ := folder.GetChildFolder()
// 获取子文件
childFiles, _ := folder.GetChildFile()
// 汇总处理结果
objects := make([]Object, 0, len(childFiles)+len(childFolders))
// 所有对象的父目录
var processedPath string
for _, folder := range childFolders {
// 路径处理钩子,
// 所有对象父目录都是一样的,所以只处理一次
if processedPath == "" {
if pathProcessor != nil {
processedPath = pathProcessor(folder.Position)
} else {
processedPath = folder.Position
}
}
objects = append(objects, Object{
ID: folder.ID,
Name: folder.Name,
Path: processedPath,
Pic: "",
Size: 0,
Type: "dir",
})
}
for _, file := range childFiles {
if processedPath == "" {
if pathProcessor != nil {
processedPath = pathProcessor(file.Dir)
} else {
processedPath = file.Dir
}
}
objects = append(objects, Object{
ID: file.ID,
Name: file.Name,
Path: processedPath,
Pic: file.PicInfo,
Size: file.Size,
Type: "file",
})
}
return objects, nil
}
// CreateDirectory 在`base`路径下创建名为`dir`的目录 TODO: test
func (fs *FileSystem) CreateDirectory(ctx context.Context, fullPath string) error { func (fs *FileSystem) CreateDirectory(ctx context.Context, fullPath string) error {
// 获取要创建目录的父路径和目录名 // 获取要创建目录的父路径和目录名
fullPath = path.Clean(fullPath) fullPath = path.Clean(fullPath)

View File

@ -7,7 +7,7 @@ import (
// CreateDirectory 创建目录 // CreateDirectory 创建目录
func CreateDirectory(c *gin.Context) { func CreateDirectory(c *gin.Context) {
var service explorer.DirectoryCreateService var service explorer.DirectoryService
if err := c.ShouldBindJSON(&service); err == nil { if err := c.ShouldBindJSON(&service); err == nil {
res := service.CreateDirectory(c) res := service.CreateDirectory(c)
c.JSON(200, res) c.JSON(200, res)
@ -15,3 +15,14 @@ func CreateDirectory(c *gin.Context) {
c.JSON(200, ErrorResponse(err)) c.JSON(200, ErrorResponse(err))
} }
} }
// ListDirectory 列出目录下内容
func ListDirectory(c *gin.Context) {
var service explorer.DirectoryService
if err := c.ShouldBindJSON(&service); err == nil {
res := service.ListDirectory(c)
c.JSON(200, res)
} else {
c.JSON(200, ErrorResponse(err))
}
}

View File

@ -37,10 +37,9 @@ func FileUploadStream(c *gin.Context) {
Name: c.Request.Header.Get("X-FileName"), Name: c.Request.Header.Get("X-FileName"),
VirtualPath: util.DotPathToStandardPath(c.Request.Header.Get("X-Path")), VirtualPath: util.DotPathToStandardPath(c.Request.Header.Get("X-Path")),
} }
user, _ := c.Get("user")
// 创建文件系统 // 创建文件系统
fs, err := filesystem.NewFileSystem(user.(*model.User)) fs, err := filesystem.NewFileSystemFromContext(c)
if err != nil { if err != nil {
c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)) c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err))
return return

View File

@ -69,6 +69,8 @@ func InitRouter() *gin.Engine {
{ {
// 创建目录 // 创建目录
directory.PUT("", controllers.CreateDirectory) directory.PUT("", controllers.CreateDirectory)
// 列出目录下内容
directory.GET("", controllers.ListDirectory)
} }
} }

View File

@ -2,22 +2,44 @@ package explorer
import ( import (
"context" "context"
model "github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/filesystem" "github.com/HFO4/cloudreve/pkg/filesystem"
"github.com/HFO4/cloudreve/pkg/serializer" "github.com/HFO4/cloudreve/pkg/serializer"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
// DirectoryCreateService 创建新目录服务 // DirectoryService 创建新目录服务
type DirectoryCreateService struct { type DirectoryService struct {
Path string `form:"newPath" json:"newPath" binding:"required,min=1,max=65535"` Path string `form:"path" json:"path" binding:"required,min=1,max=65535"`
} }
// CreateDirectory 创建目录 // ListDirectory 列出目录内容 TODO:test
func (service *DirectoryCreateService) CreateDirectory(c *gin.Context) serializer.Response { func (service *DirectoryService) ListDirectory(c *gin.Context) serializer.Response {
// 创建文件系统 // 创建文件系统
user, _ := c.Get("user") fs, err := filesystem.NewFileSystemFromContext(c)
fs, err := filesystem.NewFileSystem(user.(*model.User)) if err != nil {
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
}
// 上下文
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 获取子项目
objects, err := fs.List(ctx, service.Path, nil)
if err != nil {
return serializer.Err(serializer.CodeCreateFolderFailed, err.Error(), err)
}
return serializer.Response{
Code: 0,
Data: objects,
}
}
// CreateDirectory 创建目录 TODO:test
func (service *DirectoryService) CreateDirectory(c *gin.Context) serializer.Response {
// 创建文件系统
fs, err := filesystem.NewFileSystemFromContext(c)
if err != nil { if err != nil {
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
} }