Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
hexbee
Cloudreve
提交
36d5f514
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 搜索 >>
提交
36d5f514
编写于
12月 10, 2019
作者:
H
HFO4
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Feat: sign file source url
上级
1963a495
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
170 addition
and
43 deletion
+170
-43
middleware/auth.go
middleware/auth.go
+14
-0
models/setting.go
models/setting.go
+10
-0
pkg/auth/auth.go
pkg/auth/auth.go
+20
-0
pkg/filesystem/file.go
pkg/filesystem/file.go
+15
-4
pkg/filesystem/file_test.go
pkg/filesystem/file_test.go
+3
-2
pkg/filesystem/filesystem.go
pkg/filesystem/filesystem.go
+10
-1
pkg/filesystem/fsctx/context.go
pkg/filesystem/fsctx/context.go
+3
-1
pkg/filesystem/hooks.go
pkg/filesystem/hooks.go
+8
-7
pkg/filesystem/hooks_test.go
pkg/filesystem/hooks_test.go
+11
-10
pkg/filesystem/local/handler.go
pkg/filesystem/local/handler.go
+30
-1
pkg/filesystem/upload.go
pkg/filesystem/upload.go
+5
-4
pkg/filesystem/upload_test.go
pkg/filesystem/upload_test.go
+8
-1
routers/controllers/file.go
routers/controllers/file.go
+7
-1
routers/router.go
routers/router.go
+24
-10
service/explorer/file.go
service/explorer/file.go
+2
-1
未找到文件。
middleware/auth.go
浏览文件 @
36d5f514
package
middleware
import
(
"fmt"
"github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/serializer"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
)
// SignRequired 验证请求签名
func
SignRequired
()
gin
.
HandlerFunc
{
return
func
(
c
*
gin
.
Context
)
{
// 获取待验证的签名正文
queries
:=
c
.
Request
.
URL
.
Query
()
queries
.
Del
(
"sign"
)
c
.
Request
.
URL
.
RawQuery
=
queries
.
Encode
()
requestURI
:=
c
.
Request
.
URL
.
RequestURI
()
fmt
.
Println
(
requestURI
)
c
.
Next
()
}
}
// CurrentUser 获取登录用户
func
CurrentUser
()
gin
.
HandlerFunc
{
return
func
(
c
*
gin
.
Context
)
{
...
...
models/setting.go
浏览文件 @
36d5f514
...
...
@@ -3,6 +3,7 @@ package model
import
(
"github.com/HFO4/cloudreve/pkg/cache"
"github.com/jinzhu/gorm"
"net/url"
)
// Setting 系统设置模型
...
...
@@ -62,3 +63,12 @@ func GetSettingByType(types []string) map[string]string {
return
res
}
// GetSiteURL 获取站点地址
func
GetSiteURL
()
*
url
.
URL
{
base
,
err
:=
url
.
Parse
(
GetSettingByName
(
"siteURL"
))
if
err
!=
nil
{
base
,
_
=
url
.
Parse
(
"https://cloudreve.org"
)
}
return
base
}
pkg/auth/auth.go
浏览文件 @
36d5f514
...
...
@@ -3,6 +3,7 @@ package auth
import
(
model
"github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/serializer"
"net/url"
)
var
(
...
...
@@ -21,7 +22,26 @@ type Auth interface {
Check
(
body
string
,
sign
string
)
error
}
// SignURI 对URI进行签名
// TODO 测试
func
SignURI
(
uri
string
,
expires
int64
)
(
*
url
.
URL
,
error
)
{
// 生成签名
sign
:=
General
.
Sign
(
uri
,
expires
)
// 将签名加到URI中
base
,
err
:=
url
.
Parse
(
uri
)
if
err
!=
nil
{
return
nil
,
err
}
queries
:=
base
.
Query
()
queries
.
Set
(
"sign"
,
sign
)
base
.
RawQuery
=
queries
.
Encode
()
return
base
,
nil
}
// Init 初始化通用鉴权器
// TODO slave模式下从配置文件获取
func
Init
()
{
General
=
HMACAuth
{
SecretKey
:
[]
byte
(
model
.
GetSettingByName
(
"secret_key"
)),
...
...
pkg/filesystem/file.go
浏览文件 @
36d5f514
...
...
@@ -3,6 +3,7 @@ package filesystem
import
(
"context"
model
"github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
"github.com/HFO4/cloudreve/pkg/serializer"
"github.com/HFO4/cloudreve/pkg/util"
"github.com/juju/ratelimit"
...
...
@@ -33,8 +34,8 @@ func withSpeedLimit(rs io.ReadSeeker, speed int) io.ReadSeeker {
// AddFile 新增文件记录
func
(
fs
*
FileSystem
)
AddFile
(
ctx
context
.
Context
,
parent
*
model
.
Folder
)
(
*
model
.
File
,
error
)
{
file
:=
ctx
.
Value
(
FileHeaderCtx
)
.
(
FileHeader
)
filePath
:=
ctx
.
Value
(
SavePathCtx
)
.
(
string
)
file
:=
ctx
.
Value
(
fsctx
.
FileHeaderCtx
)
.
(
FileHeader
)
filePath
:=
ctx
.
Value
(
fsctx
.
SavePathCtx
)
.
(
string
)
newFile
:=
model
.
File
{
Name
:
file
.
GetFileName
(),
...
...
@@ -86,7 +87,7 @@ func (fs *FileSystem) GetContent(ctx context.Context, path string) (io.ReadSeeke
return
nil
,
ErrObjectNotExist
}
fs
.
FileTarget
=
[]
model
.
File
{
*
file
}
ctx
=
context
.
WithValue
(
ctx
,
fsctx
.
FileModelCtx
,
file
)
// 将当前存储策略重设为文件使用的
fs
.
Policy
=
file
.
GetPolicy
()
err
=
fs
.
dispatchHandler
()
...
...
@@ -161,6 +162,8 @@ func (fs *FileSystem) GetSource(ctx context.Context, fileID uint) (string, error
}
fs
.
FileTarget
=
[]
model
.
File
{
fileObject
[
0
]}
ctx
=
context
.
WithValue
(
ctx
,
fsctx
.
FileModelCtx
,
fileObject
[
0
])
// 将当前存储策略重设为文件使用的
fs
.
Policy
=
fileObject
[
0
]
.
GetPolicy
()
err
=
fs
.
dispatchHandler
()
...
...
@@ -172,5 +175,13 @@ func (fs *FileSystem) GetSource(ctx context.Context, fileID uint) (string, error
if
!
fs
.
Policy
.
IsOriginLinkEnable
{
return
""
,
serializer
.
NewError
(
serializer
.
CodePolicyNotAllowed
,
"当前存储策略无法获得外链"
,
nil
)
}
return
""
,
nil
// 生成外链地址
siteURL
:=
model
.
GetSiteURL
()
source
,
err
:=
fs
.
Handler
.
Source
(
ctx
,
fileObject
[
0
]
.
SourceName
,
*
siteURL
,
0
)
if
err
!=
nil
{
return
""
,
serializer
.
NewError
(
serializer
.
CodeNotSet
,
"无法获取外链"
,
err
)
}
return
source
,
nil
}
pkg/filesystem/file_test.go
浏览文件 @
36d5f514
...
...
@@ -4,6 +4,7 @@ import (
"context"
"github.com/DATA-DOG/go-sqlmock"
model
"github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
"github.com/HFO4/cloudreve/pkg/filesystem/local"
"github.com/HFO4/cloudreve/pkg/serializer"
"github.com/jinzhu/gorm"
...
...
@@ -35,8 +36,8 @@ func TestFileSystem_AddFile(t *testing.T) {
},
},
}
ctx
:=
context
.
WithValue
(
context
.
Background
(),
FileHeaderCtx
,
file
)
ctx
=
context
.
WithValue
(
ctx
,
SavePathCtx
,
"/Uploads/1_sad.txt"
)
ctx
:=
context
.
WithValue
(
context
.
Background
(),
fsctx
.
FileHeaderCtx
,
file
)
ctx
=
context
.
WithValue
(
ctx
,
fsctx
.
SavePathCtx
,
"/Uploads/1_sad.txt"
)
_
,
err
:=
fs
.
AddFile
(
ctx
,
&
folder
)
...
...
pkg/filesystem/filesystem.go
浏览文件 @
36d5f514
...
...
@@ -8,6 +8,7 @@ import (
"github.com/HFO4/cloudreve/pkg/filesystem/response"
"github.com/gin-gonic/gin"
"io"
"net/url"
)
// FileHeader 上传来的文件数据处理器
...
...
@@ -30,6 +31,8 @@ type Handler interface {
Get
(
ctx
context
.
Context
,
path
string
)
(
io
.
ReadSeeker
,
error
)
// 获取缩略图
Thumb
(
ctx
context
.
Context
,
path
string
)
(
*
response
.
ContentResponse
,
error
)
// 获取外链地址,url
Source
(
ctx
context
.
Context
,
path
string
,
url
url
.
URL
,
expires
int64
)
(
string
,
error
)
}
// FileSystem 管理文件的文件系统
...
...
@@ -79,17 +82,23 @@ func NewFileSystem(user *model.User) (*FileSystem, error) {
// dispatchHandler 根据存储策略分配文件适配器
func
(
fs
*
FileSystem
)
dispatchHandler
()
error
{
var
policyType
string
var
currentPolicy
*
model
.
Policy
if
fs
.
Policy
==
nil
{
// 如果没有具体指定,就是用用户当前存储策略
policyType
=
fs
.
User
.
Policy
.
Type
currentPolicy
=
&
fs
.
User
.
Policy
}
else
{
policyType
=
fs
.
Policy
.
Type
currentPolicy
=
fs
.
Policy
}
// 根据存储策略类型分配适配器
switch
policyType
{
case
"local"
:
fs
.
Handler
=
local
.
Handler
{}
fs
.
Handler
=
local
.
Handler
{
Policy
:
currentPolicy
,
}
return
nil
default
:
return
ErrUnknownPolicyType
...
...
pkg/filesystem/context.go
→
pkg/filesystem/
fsctx/
context.go
浏览文件 @
36d5f514
package
f
ilesystem
package
f
sctx
type
key
int
...
...
@@ -11,4 +11,6 @@ const (
FileHeaderCtx
// PathCtx 文件或目录的虚拟路径
PathCtx
// FileModelCtx 文件数据库模型
FileModelCtx
)
pkg/filesystem/hooks.go
浏览文件 @
36d5f514
...
...
@@ -3,6 +3,7 @@ package filesystem
import
(
"context"
"errors"
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
"github.com/HFO4/cloudreve/pkg/util"
)
...
...
@@ -40,7 +41,7 @@ func (fs *FileSystem) Trigger(ctx context.Context, hooks []Hook) error {
// HookIsFileExist 检查虚拟路径文件是否存在
func
HookIsFileExist
(
ctx
context
.
Context
,
fs
*
FileSystem
)
error
{
filePath
:=
ctx
.
Value
(
PathCtx
)
.
(
string
)
filePath
:=
ctx
.
Value
(
fsctx
.
PathCtx
)
.
(
string
)
if
ok
,
_
:=
fs
.
IsFileExist
(
filePath
);
ok
{
return
nil
}
...
...
@@ -49,7 +50,7 @@ func HookIsFileExist(ctx context.Context, fs *FileSystem) error {
// HookValidateFile 一系列对文件检验的集合
func
HookValidateFile
(
ctx
context
.
Context
,
fs
*
FileSystem
)
error
{
file
:=
ctx
.
Value
(
FileHeaderCtx
)
.
(
FileHeader
)
file
:=
ctx
.
Value
(
fsctx
.
FileHeaderCtx
)
.
(
FileHeader
)
// 验证单文件尺寸
if
!
fs
.
ValidateFileSize
(
ctx
,
file
.
GetSize
())
{
...
...
@@ -72,7 +73,7 @@ func HookValidateFile(ctx context.Context, fs *FileSystem) error {
// HookValidateCapacity 验证并扣除用户容量,包含数据库操作
func
HookValidateCapacity
(
ctx
context
.
Context
,
fs
*
FileSystem
)
error
{
file
:=
ctx
.
Value
(
FileHeaderCtx
)
.
(
FileHeader
)
file
:=
ctx
.
Value
(
fsctx
.
FileHeaderCtx
)
.
(
FileHeader
)
// 验证并扣除容量
if
!
fs
.
ValidateCapacity
(
ctx
,
file
.
GetSize
())
{
return
ErrInsufficientCapacity
...
...
@@ -82,7 +83,7 @@ func HookValidateCapacity(ctx context.Context, fs *FileSystem) error {
// HookDeleteTempFile 删除已保存的临时文件
func
HookDeleteTempFile
(
ctx
context
.
Context
,
fs
*
FileSystem
)
error
{
filePath
:=
ctx
.
Value
(
SavePathCtx
)
.
(
string
)
filePath
:=
ctx
.
Value
(
fsctx
.
SavePathCtx
)
.
(
string
)
// 删除临时文件
if
util
.
Exists
(
filePath
)
{
_
,
err
:=
fs
.
Handler
.
Delete
(
ctx
,
[]
string
{
filePath
})
...
...
@@ -96,7 +97,7 @@ func HookDeleteTempFile(ctx context.Context, fs *FileSystem) error {
// HookGiveBackCapacity 归还用户容量
func
HookGiveBackCapacity
(
ctx
context
.
Context
,
fs
*
FileSystem
)
error
{
file
:=
ctx
.
Value
(
FileHeaderCtx
)
.
(
FileHeader
)
file
:=
ctx
.
Value
(
fsctx
.
FileHeaderCtx
)
.
(
FileHeader
)
// 归还用户容量
if
!
fs
.
User
.
DeductionStorage
(
file
.
GetSize
())
{
...
...
@@ -108,7 +109,7 @@ func HookGiveBackCapacity(ctx context.Context, fs *FileSystem) error {
// GenericAfterUpload 文件上传完成后,包含数据库操作
func
GenericAfterUpload
(
ctx
context
.
Context
,
fs
*
FileSystem
)
error
{
// 文件存放的虚拟路径
virtualPath
:=
ctx
.
Value
(
FileHeaderCtx
)
.
(
FileHeader
)
.
GetVirtualPath
()
virtualPath
:=
ctx
.
Value
(
fsctx
.
FileHeaderCtx
)
.
(
FileHeader
)
.
GetVirtualPath
()
// 检查路径是否存在
isExist
,
folder
:=
fs
.
IsPathExist
(
virtualPath
)
...
...
@@ -119,7 +120,7 @@ func GenericAfterUpload(ctx context.Context, fs *FileSystem) error {
// 检查文件是否存在
if
ok
,
_
:=
fs
.
IsChildFileExist
(
folder
,
ctx
.
Value
(
FileHeaderCtx
)
.
(
FileHeader
)
.
GetFileName
(),
ctx
.
Value
(
fsctx
.
FileHeaderCtx
)
.
(
FileHeader
)
.
GetFileName
(),
);
ok
{
return
ErrFileExisted
}
...
...
pkg/filesystem/hooks_test.go
浏览文件 @
36d5f514
...
...
@@ -5,6 +5,7 @@ import (
"errors"
"github.com/DATA-DOG/go-sqlmock"
model
"github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
"github.com/HFO4/cloudreve/pkg/filesystem/local"
"github.com/jinzhu/gorm"
"github.com/stretchr/testify/assert"
...
...
@@ -18,7 +19,7 @@ func TestGenericBeforeUpload(t *testing.T) {
Size
:
5
,
Name
:
"1.txt"
,
}
ctx
:=
context
.
WithValue
(
context
.
Background
(),
FileHeaderCtx
,
file
)
ctx
:=
context
.
WithValue
(
context
.
Background
(),
fsctx
.
FileHeaderCtx
,
file
)
fs
:=
FileSystem
{
User
:
&
model
.
User
{
Storage
:
0
,
...
...
@@ -38,15 +39,15 @@ func TestGenericBeforeUpload(t *testing.T) {
file
.
Size
=
1
file
.
Name
=
"1"
ctx
=
context
.
WithValue
(
context
.
Background
(),
FileHeaderCtx
,
file
)
ctx
=
context
.
WithValue
(
context
.
Background
(),
fsctx
.
FileHeaderCtx
,
file
)
asserts
.
Error
(
HookValidateFile
(
ctx
,
&
fs
))
file
.
Name
=
"1.txt"
ctx
=
context
.
WithValue
(
context
.
Background
(),
FileHeaderCtx
,
file
)
ctx
=
context
.
WithValue
(
context
.
Background
(),
fsctx
.
FileHeaderCtx
,
file
)
asserts
.
NoError
(
HookValidateFile
(
ctx
,
&
fs
))
file
.
Name
=
"1.t/xt"
ctx
=
context
.
WithValue
(
context
.
Background
(),
FileHeaderCtx
,
file
)
ctx
=
context
.
WithValue
(
context
.
Background
(),
fsctx
.
FileHeaderCtx
,
file
)
asserts
.
Error
(
HookValidateFile
(
ctx
,
&
fs
))
}
...
...
@@ -59,8 +60,8 @@ func TestGenericAfterUploadCanceled(t *testing.T) {
Size
:
5
,
Name
:
"TestGenericAfterUploadCanceled"
,
}
ctx
:=
context
.
WithValue
(
context
.
Background
(),
SavePathCtx
,
"TestGenericAfterUploadCanceled"
)
ctx
=
context
.
WithValue
(
ctx
,
FileHeaderCtx
,
file
)
ctx
:=
context
.
WithValue
(
context
.
Background
(),
fsctx
.
SavePathCtx
,
"TestGenericAfterUploadCanceled"
)
ctx
=
context
.
WithValue
(
ctx
,
fsctx
.
FileHeaderCtx
,
file
)
fs
:=
FileSystem
{
User
:
&
model
.
User
{
Storage
:
5
},
Handler
:
local
.
Handler
{},
...
...
@@ -97,11 +98,11 @@ func TestGenericAfterUpload(t *testing.T) {
},
}
ctx
:=
context
.
WithValue
(
context
.
Background
(),
FileHeaderCtx
,
local
.
FileStream
{
ctx
:=
context
.
WithValue
(
context
.
Background
(),
fsctx
.
FileHeaderCtx
,
local
.
FileStream
{
VirtualPath
:
"/我的文件"
,
Name
:
"test.txt"
,
})
ctx
=
context
.
WithValue
(
ctx
,
SavePathCtx
,
""
)
ctx
=
context
.
WithValue
(
ctx
,
fsctx
.
SavePathCtx
,
""
)
// 正常
mock
.
ExpectQuery
(
"SELECT(.+)"
)
.
...
...
@@ -228,7 +229,7 @@ func TestHookIsFileExist(t *testing.T) {
ID
:
1
,
},
}}
ctx
:=
context
.
WithValue
(
context
.
Background
(),
PathCtx
,
"/test.txt"
)
ctx
:=
context
.
WithValue
(
context
.
Background
(),
fsctx
.
PathCtx
,
"/test.txt"
)
{
mock
.
ExpectQuery
(
"SELECT(.+)"
)
.
WithArgs
(
1
)
.
...
...
@@ -263,7 +264,7 @@ func TestHookValidateCapacity(t *testing.T) {
MaxStorage
:
11
,
},
}}
ctx
:=
context
.
WithValue
(
context
.
Background
(),
FileHeaderCtx
,
local
.
FileStream
{
Size
:
10
})
ctx
:=
context
.
WithValue
(
context
.
Background
(),
fsctx
.
FileHeaderCtx
,
local
.
FileStream
{
Size
:
10
})
{
err
:=
HookValidateCapacity
(
ctx
,
fs
)
asserts
.
NoError
(
err
)
...
...
pkg/filesystem/local/handler.go
浏览文件 @
36d5f514
...
...
@@ -2,16 +2,25 @@ package local
import
(
"context"
"errors"
"fmt"
model
"github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/auth"
"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"
"io"
"net/url"
"os"
"path/filepath"
)
// Handler 本地策略适配器
type
Handler
struct
{}
type
Handler
struct
{
Policy
*
model
.
Policy
}
// Get 获取文件内容
func
(
handler
Handler
)
Get
(
ctx
context
.
Context
,
path
string
)
(
io
.
ReadSeeker
,
error
)
{
...
...
@@ -97,3 +106,23 @@ func (handler Handler) Thumb(ctx context.Context, path string) (*response.Conten
Content
:
file
,
},
nil
}
// Source 获取外链URL
func
(
handler
Handler
)
Source
(
ctx
context
.
Context
,
path
string
,
url
url
.
URL
,
expires
int64
)
(
string
,
error
)
{
file
,
ok
:=
ctx
.
Value
(
fsctx
.
FileModelCtx
)
.
(
model
.
File
)
if
!
ok
{
return
""
,
errors
.
New
(
"无法获取文件记录上下文"
)
}
// 签名生成文件记录
signedURI
,
err
:=
auth
.
SignURI
(
fmt
.
Sprintf
(
"/api/v3/file/get/%d/%s"
,
file
.
ID
,
file
.
Name
),
0
,
)
if
err
!=
nil
{
return
""
,
serializer
.
NewError
(
serializer
.
CodeEncryptError
,
"无法对URL进行签名"
,
err
)
}
finalURL
:=
url
.
ResolveReference
(
signedURI
)
.
String
()
return
finalURL
,
nil
}
pkg/filesystem/upload.go
浏览文件 @
36d5f514
...
...
@@ -2,6 +2,7 @@ package filesystem
import
(
"context"
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
"github.com/HFO4/cloudreve/pkg/util"
"github.com/gin-gonic/gin"
"path/filepath"
...
...
@@ -14,7 +15,7 @@ import (
// Upload 上传文件
func
(
fs
*
FileSystem
)
Upload
(
ctx
context
.
Context
,
file
FileHeader
)
(
err
error
)
{
ctx
=
context
.
WithValue
(
ctx
,
FileHeaderCtx
,
file
)
ctx
=
context
.
WithValue
(
ctx
,
fsctx
.
FileHeaderCtx
,
file
)
// 上传前的钩子
err
=
fs
.
Trigger
(
ctx
,
fs
.
BeforeUpload
)
...
...
@@ -35,7 +36,7 @@ func (fs *FileSystem) Upload(ctx context.Context, file FileHeader) (err error) {
}
// 上传完成后的钩子
ctx
=
context
.
WithValue
(
ctx
,
SavePathCtx
,
savePath
)
ctx
=
context
.
WithValue
(
ctx
,
fsctx
.
SavePathCtx
,
savePath
)
err
=
fs
.
Trigger
(
ctx
,
fs
.
AfterUpload
)
if
err
!=
nil
{
...
...
@@ -70,7 +71,7 @@ func (fs *FileSystem) GenerateSavePath(ctx context.Context, file FileHeader) str
// CancelUpload 监测客户端取消上传
func
(
fs
*
FileSystem
)
CancelUpload
(
ctx
context
.
Context
,
path
string
,
file
FileHeader
)
{
ginCtx
:=
ctx
.
Value
(
GinCtx
)
.
(
*
gin
.
Context
)
ginCtx
:=
ctx
.
Value
(
fsctx
.
GinCtx
)
.
(
*
gin
.
Context
)
select
{
case
<-
ginCtx
.
Request
.
Context
()
.
Done
()
:
select
{
...
...
@@ -82,7 +83,7 @@ func (fs *FileSystem) CancelUpload(ctx context.Context, path string, file FileHe
if
fs
.
AfterUploadCanceled
==
nil
{
return
}
ctx
=
context
.
WithValue
(
ctx
,
SavePathCtx
,
path
)
ctx
=
context
.
WithValue
(
ctx
,
fsctx
.
SavePathCtx
,
path
)
err
:=
fs
.
Trigger
(
ctx
,
fs
.
AfterUploadCanceled
)
if
err
!=
nil
{
util
.
Log
()
.
Debug
(
"执行 AfterUploadCanceled 钩子出错,%s"
,
err
)
...
...
pkg/filesystem/upload_test.go
浏览文件 @
36d5f514
...
...
@@ -4,6 +4,7 @@ import (
"context"
"errors"
model
"github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
"github.com/HFO4/cloudreve/pkg/filesystem/local"
"github.com/HFO4/cloudreve/pkg/filesystem/response"
"github.com/gin-gonic/gin"
...
...
@@ -13,6 +14,7 @@ import (
"io"
"net/http"
"net/http/httptest"
"net/url"
"testing"
)
...
...
@@ -40,6 +42,11 @@ func (m FileHeaderMock) Thumb(ctx context.Context, files string) (*response.Cont
return
args
.
Get
(
0
)
.
(
*
response
.
ContentResponse
),
args
.
Error
(
1
)
}
func
(
m
FileHeaderMock
)
Source
(
ctx
context
.
Context
,
path
string
,
url
url
.
URL
,
expires
int64
)
(
string
,
error
)
{
args
:=
m
.
Called
(
ctx
,
path
,
url
,
expires
)
return
args
.
Get
(
0
)
.
(
string
),
args
.
Error
(
1
)
}
func
TestFileSystem_Upload
(
t
*
testing
.
T
)
{
asserts
:=
assert
.
New
(
t
)
...
...
@@ -61,7 +68,7 @@ func TestFileSystem_Upload(t *testing.T) {
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
c
,
_
:=
gin
.
CreateTestContext
(
httptest
.
NewRecorder
())
c
.
Request
,
_
=
http
.
NewRequest
(
"POST"
,
"/"
,
nil
)
ctx
=
context
.
WithValue
(
ctx
,
GinCtx
,
c
)
ctx
=
context
.
WithValue
(
ctx
,
fsctx
.
GinCtx
,
c
)
cancel
()
file
:=
local
.
FileStream
{
Size
:
5
,
...
...
routers/controllers/file.go
浏览文件 @
36d5f514
...
...
@@ -5,6 +5,7 @@ import (
"context"
"github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/filesystem"
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
"github.com/HFO4/cloudreve/pkg/filesystem/local"
"github.com/HFO4/cloudreve/pkg/serializer"
"github.com/HFO4/cloudreve/pkg/util"
...
...
@@ -15,6 +16,11 @@ import (
"strconv"
)
// AnonymousGetContent 匿名获取文件资源
func
AnonymousGetContent
(
c
*
gin
.
Context
)
{
c
.
JSON
(
200
,
serializer
.
Response
{})
}
// GetSource 获取文件的外链地址
func
GetSource
(
c
*
gin
.
Context
)
{
// 创建上下文
...
...
@@ -152,7 +158,7 @@ func FileUploadStream(c *gin.Context) {
fs
.
Use
(
"AfterValidateFailed"
,
filesystem
.
HookGiveBackCapacity
)
// 执行上传
uploadCtx
:=
context
.
WithValue
(
ctx
,
f
ilesystem
.
GinCtx
,
c
)
uploadCtx
:=
context
.
WithValue
(
ctx
,
f
sctx
.
GinCtx
,
c
)
err
=
fs
.
Upload
(
uploadCtx
,
fileData
)
if
err
!=
nil
{
c
.
JSON
(
200
,
serializer
.
Err
(
serializer
.
CodeUploadFailed
,
err
.
Error
(),
err
))
...
...
routers/router.go
浏览文件 @
36d5f514
...
...
@@ -39,23 +39,37 @@ func InitRouter() *gin.Engine {
*/
v3
:=
r
.
Group
(
"/api/v3"
)
{
// 测试用路由
v3
.
GET
(
"site/ping"
,
controllers
.
Ping
)
// 全局设置相关
site
:=
v3
.
Group
(
"site"
)
{
// 测试用路由
site
.
GET
(
"ping"
,
controllers
.
Ping
)
// 验证码
site
.
GET
(
"captcha"
,
controllers
.
Captcha
)
// 站点全局配置
site
.
GET
(
"config"
,
controllers
.
SiteConfig
)
}
// 不需要登录的用户相关路由
// 用户相关路由
user
:=
v3
.
Group
(
"user"
)
{
// 用户登录
v3
.
POST
(
"user/
session"
,
controllers
.
UserLogin
)
user
.
POST
(
"
session"
,
controllers
.
UserLogin
)
// WebAuthn登陆初始化
v3
.
GET
(
"user/
authn/:username"
,
controllers
.
StartLoginAuthn
)
user
.
GET
(
"
authn/:username"
,
controllers
.
StartLoginAuthn
)
// WebAuthn登陆
v3
.
POST
(
"user/
authn/finish/:username"
,
controllers
.
FinishLoginAuthn
)
user
.
POST
(
"
authn/finish/:username"
,
controllers
.
FinishLoginAuthn
)
}
// 验证码
v3
.
GET
(
"captcha"
,
controllers
.
Captcha
)
// 站点全局配置
v3
.
GET
(
"site/config"
,
controllers
.
SiteConfig
)
// 需要携带签名验证的
sign
:=
v3
.
Group
(
""
)
sign
.
Use
(
middleware
.
SignRequired
())
{
file
:=
sign
.
Group
(
"file"
)
{
file
.
GET
(
"get/:id/:name"
,
controllers
.
AnonymousGetContent
)
}
}
// 需要登录保护的
auth
:=
v3
.
Group
(
""
)
...
...
service/explorer/file.go
浏览文件 @
36d5f514
...
...
@@ -3,6 +3,7 @@ package explorer
import
(
"context"
"github.com/HFO4/cloudreve/pkg/filesystem"
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
"github.com/HFO4/cloudreve/pkg/serializer"
"github.com/gin-gonic/gin"
"net/http"
...
...
@@ -22,7 +23,7 @@ func (service *FileDownloadService) Download(ctx context.Context, c *gin.Context
}
// 开始处理下载
ctx
=
context
.
WithValue
(
ctx
,
f
ilesystem
.
GinCtx
,
c
)
ctx
=
context
.
WithValue
(
ctx
,
f
sctx
.
GinCtx
,
c
)
rs
,
err
:=
fs
.
GetDownloadContent
(
ctx
,
service
.
Path
)
if
err
!=
nil
{
return
serializer
.
Err
(
serializer
.
CodeNotSet
,
err
.
Error
(),
err
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录