Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
hexbee
Cloudreve
提交
e8a6df9a
C
Cloudreve
项目概览
hexbee
/
Cloudreve
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
Cloudreve
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
e8a6df9a
编写于
5月 02, 2020
作者:
H
HFO4
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Feat: import file from existing outer folder
上级
b02d27ca
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
169 addition
and
2 deletion
+169
-2
assets
assets
+1
-1
models/policy.go
models/policy.go
+5
-0
models/policy_test.go
models/policy_test.go
+2
-0
pkg/filesystem/manage.go
pkg/filesystem/manage.go
+32
-0
pkg/filesystem/manage_test.go
pkg/filesystem/manage_test.go
+48
-0
pkg/filesystem/upload_test.go
pkg/filesystem/upload_test.go
+2
-1
routers/controllers/admin.go
routers/controllers/admin.go
+11
-0
routers/router.go
routers/router.go
+3
-0
service/admin/file.go
service/admin/file.go
+65
-0
未找到文件。
assets
@
df766e44
比较
10e5497c
...
df766e44
Subproject commit
10e5497cfb9f2c180f28a5a492745f521c4b72b1
Subproject commit
df766e44387528370bfa913b094ad16898a013a2
models/policy.go
浏览文件 @
e8a6df9a
...
...
@@ -222,6 +222,11 @@ func (policy *Policy) IsThumbGenerateNeeded() bool {
return
policy
.
Type
==
"local"
}
// CanStructureBeListed 返回存储策略是否能被前台列物理目录
func
(
policy
*
Policy
)
CanStructureBeListed
()
bool
{
return
policy
.
Type
!=
"local"
&&
policy
.
Type
!=
"remote"
}
// GetUploadURL 获取文件上传服务API地址
func
(
policy
*
Policy
)
GetUploadURL
()
string
{
server
,
err
:=
url
.
Parse
(
policy
.
Server
)
...
...
models/policy_test.go
浏览文件 @
e8a6df9a
...
...
@@ -246,9 +246,11 @@ func TestPolicy_Props(t *testing.T) {
asserts
.
True
(
policy
.
IsPathGenerateNeeded
())
asserts
.
True
(
policy
.
IsTransitUpload
(
4
))
asserts
.
False
(
policy
.
IsTransitUpload
(
5
*
1024
*
1024
))
asserts
.
True
(
policy
.
CanStructureBeListed
())
policy
.
Type
=
"local"
asserts
.
True
(
policy
.
IsThumbGenerateNeeded
())
asserts
.
True
(
policy
.
IsPathGenerateNeeded
())
asserts
.
False
(
policy
.
CanStructureBeListed
())
}
func
TestPolicy_IsThumbExist
(
t
*
testing
.
T
)
{
...
...
pkg/filesystem/manage.go
浏览文件 @
e8a6df9a
...
...
@@ -285,6 +285,38 @@ func (fs *FileSystem) List(ctx context.Context, dirPath string, pathProcessor fu
return
fs
.
listObjects
(
ctx
,
parentPath
,
childFiles
,
childFolders
,
pathProcessor
),
nil
}
// ListPhysical 列出存储策略中的外部目录
// TODO:测试
func
(
fs
*
FileSystem
)
ListPhysical
(
ctx
context
.
Context
,
dirPath
string
)
([]
Object
,
error
)
{
if
err
:=
fs
.
DispatchHandler
();
fs
.
Policy
==
nil
||
err
!=
nil
{
return
nil
,
ErrUnknownPolicyType
}
// 存储策略不支持列取时,返回空结果
if
!
fs
.
Policy
.
CanStructureBeListed
()
{
return
nil
,
nil
}
// 列取路径
objects
,
err
:=
fs
.
Handler
.
List
(
ctx
,
dirPath
,
false
)
if
err
!=
nil
{
return
nil
,
err
}
var
(
folders
[]
model
.
Folder
)
for
_
,
object
:=
range
objects
{
if
object
.
IsDir
{
folders
=
append
(
folders
,
model
.
Folder
{
Name
:
object
.
Name
,
})
}
}
return
fs
.
listObjects
(
ctx
,
dirPath
,
nil
,
folders
,
nil
),
nil
}
func
(
fs
*
FileSystem
)
listObjects
(
ctx
context
.
Context
,
parent
string
,
files
[]
model
.
File
,
folders
[]
model
.
Folder
,
pathProcessor
func
(
string
)
string
)
[]
Object
{
// 分享文件的ID
shareKey
:=
""
...
...
pkg/filesystem/manage_test.go
浏览文件 @
e8a6df9a
...
...
@@ -8,14 +8,62 @@ import (
"github.com/HFO4/cloudreve/pkg/cache"
"github.com/HFO4/cloudreve/pkg/conf"
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
"github.com/HFO4/cloudreve/pkg/filesystem/response"
"github.com/HFO4/cloudreve/pkg/serializer"
"github.com/HFO4/cloudreve/pkg/util"
"github.com/jinzhu/gorm"
"github.com/stretchr/testify/assert"
testMock
"github.com/stretchr/testify/mock"
"os"
"testing"
)
func
TestFileSystem_ListPhysical
(
t
*
testing
.
T
)
{
asserts
:=
assert
.
New
(
t
)
fs
:=
&
FileSystem
{
User
:
&
model
.
User
{
Model
:
gorm
.
Model
{
ID
:
1
,
},
},
Policy
:
&
model
.
Policy
{
Type
:
"mock"
},
}
ctx
:=
context
.
Background
()
// 未知存储策略
{
fs
.
Policy
.
Type
=
"unknown"
res
,
err
:=
fs
.
ListPhysical
(
ctx
,
"/"
)
asserts
.
Equal
(
ErrUnknownPolicyType
,
err
)
asserts
.
Empty
(
res
)
fs
.
Policy
.
Type
=
"mock"
}
// 无法列取目录
{
testHandler
:=
new
(
FileHeaderMock
)
testHandler
.
On
(
"List"
,
testMock
.
Anything
,
"/"
,
testMock
.
Anything
)
.
Return
([]
response
.
Object
{},
errors
.
New
(
"error"
))
fs
.
Handler
=
testHandler
res
,
err
:=
fs
.
ListPhysical
(
ctx
,
"/"
)
asserts
.
EqualError
(
err
,
"error"
)
asserts
.
Empty
(
res
)
}
// 成功
{
testHandler
:=
new
(
FileHeaderMock
)
testHandler
.
On
(
"List"
,
testMock
.
Anything
,
"/"
,
testMock
.
Anything
)
.
Return
(
[]
response
.
Object
{{
IsDir
:
true
,
Name
:
"1"
},
{
IsDir
:
false
,
Name
:
"2"
}},
nil
,
)
fs
.
Handler
=
testHandler
res
,
err
:=
fs
.
ListPhysical
(
ctx
,
"/"
)
asserts
.
NoError
(
err
)
asserts
.
Len
(
res
,
1
)
asserts
.
Equal
(
"1"
,
res
[
0
]
.
Name
)
}
}
func
TestFileSystem_List
(
t
*
testing
.
T
)
{
asserts
:=
assert
.
New
(
t
)
fs
:=
&
FileSystem
{
User
:
&
model
.
User
{
...
...
pkg/filesystem/upload_test.go
浏览文件 @
e8a6df9a
...
...
@@ -27,7 +27,8 @@ type FileHeaderMock struct {
}
func
(
m
FileHeaderMock
)
List
(
ctx
context
.
Context
,
path
string
,
recursive
bool
)
([]
response
.
Object
,
error
)
{
panic
(
"implement me"
)
args
:=
m
.
Called
(
ctx
,
path
,
recursive
)
return
args
.
Get
(
0
)
.
([]
response
.
Object
),
args
.
Error
(
1
)
}
func
(
m
FileHeaderMock
)
Get
(
ctx
context
.
Context
,
path
string
)
(
response
.
RSCloser
,
error
)
{
...
...
routers/controllers/admin.go
浏览文件 @
e8a6df9a
...
...
@@ -413,3 +413,14 @@ func AdminCreateImportTask(c *gin.Context) {
c
.
JSON
(
200
,
ErrorResponse
(
err
))
}
}
// AdminListFolders 列出用户或外部文件系统目录
func
AdminListFolders
(
c
*
gin
.
Context
)
{
var
service
admin
.
ListFolderService
if
err
:=
c
.
ShouldBindUri
(
&
service
);
err
==
nil
{
res
:=
service
.
List
(
c
)
c
.
JSON
(
200
,
res
)
}
else
{
c
.
JSON
(
200
,
ErrorResponse
(
err
))
}
}
routers/router.go
浏览文件 @
e8a6df9a
...
...
@@ -367,6 +367,9 @@ func InitMasterRouter() *gin.Engine {
file
.
GET
(
"preview/:id"
,
controllers
.
AdminGetFile
)
// 删除
file
.
POST
(
"delete"
,
controllers
.
AdminDeleteFile
)
// 列出用户或外部文件系统目录
file
.
GET
(
"folders/:type/:id/*path"
,
controllers
.
AdminListFolders
)
}
share
:=
admin
.
Group
(
"share"
)
...
...
service/admin/file.go
浏览文件 @
e8a6df9a
...
...
@@ -22,6 +22,71 @@ type FileBatchService struct {
Force
bool
`json:"force"`
}
// ListFolderService 列目录结构
type
ListFolderService
struct
{
Path
string
`uri:"path" binding:"required,max=65535"`
ID
uint
`uri:"id" binding:"required"`
Type
string
`uri:"type" binding:"eq=policy|eq=user"`
}
// List 列出指定路径下的目录
func
(
service
*
ListFolderService
)
List
(
c
*
gin
.
Context
)
serializer
.
Response
{
if
service
.
Type
==
"policy"
{
// 列取存储策略中的目录
policy
,
err
:=
model
.
GetPolicyByID
(
service
.
ID
)
if
err
!=
nil
{
return
serializer
.
Err
(
serializer
.
CodeNotFound
,
"存储策略不存在"
,
err
)
}
// 创建文件系统
fs
,
err
:=
filesystem
.
NewAnonymousFileSystem
()
if
err
!=
nil
{
return
serializer
.
Err
(
serializer
.
CodeInternalSetting
,
"无法创建文件系统"
,
err
)
}
defer
fs
.
Recycle
()
// 列取存储策略中的文件
fs
.
Policy
=
&
policy
res
,
err
:=
fs
.
ListPhysical
(
c
.
Request
.
Context
(),
service
.
Path
)
if
err
!=
nil
{
return
serializer
.
Err
(
serializer
.
CodeIOFailed
,
"无法列取目录"
,
err
)
}
return
serializer
.
Response
{
Data
:
map
[
string
]
interface
{}{
"objects"
:
res
,
},
}
}
// 列取用户空间目录
// 查找用户
user
,
err
:=
model
.
GetUserByID
(
service
.
ID
)
if
err
!=
nil
{
return
serializer
.
Err
(
serializer
.
CodeNotFound
,
"用户不存在"
,
err
)
}
// 创建文件系统
fs
,
err
:=
filesystem
.
NewFileSystem
(
&
user
)
if
err
!=
nil
{
return
serializer
.
Err
(
serializer
.
CodeInternalSetting
,
"无法创建文件系统"
,
err
)
}
defer
fs
.
Recycle
()
// 列取目录
res
,
err
:=
fs
.
List
(
c
.
Request
.
Context
(),
service
.
Path
,
nil
)
if
err
!=
nil
{
return
serializer
.
Err
(
serializer
.
CodeIOFailed
,
"无法列取目录"
,
err
)
}
return
serializer
.
Response
{
Data
:
map
[
string
]
interface
{}{
"objects"
:
res
,
},
}
}
// Delete 删除文件
func
(
service
*
FileBatchService
)
Delete
(
c
*
gin
.
Context
)
serializer
.
Response
{
files
,
err
:=
model
.
GetFilesByIDs
(
service
.
ID
,
0
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录