diff --git a/pkg/filesystem/file.go b/pkg/filesystem/file.go index 7f43778..d9ae304 100644 --- a/pkg/filesystem/file.go +++ b/pkg/filesystem/file.go @@ -2,7 +2,10 @@ package filesystem import ( "context" + "errors" model "github.com/HFO4/cloudreve/models" + "github.com/HFO4/cloudreve/pkg/serializer" + "io" ) /* ============ @@ -32,3 +35,8 @@ func (fs *FileSystem) AddFile(ctx context.Context, parent *model.Folder) (*model return &newFile, nil } + +// Download 处理下载文件请求 +func (fs *FileSystem) Download(ctx context.Context, path string) (io.ReadCloser, error) { + return nil, serializer.NewError(serializer.CodeEncryptError, "人都的", errors.New("不是人都的")) +} diff --git a/pkg/serializer/common.go b/pkg/serializer/error.go similarity index 71% rename from pkg/serializer/common.go rename to pkg/serializer/error.go index a65aaf8..b57177a 100644 --- a/pkg/serializer/common.go +++ b/pkg/serializer/error.go @@ -10,6 +10,27 @@ type Response struct { Error string `json:"error,omitempty"` } +// AppError 应用错误,实现了error接口 +type AppError struct { + Code int + Msg string + RawError error +} + +// NewError 返回新的错误对象 todo:测试 还有下面的 +func NewError(code int, msg string, err error) AppError { + return AppError{ + Code: code, + Msg: msg, + RawError: err, + } +} + +// Error 返回业务代码确定的可读错误信息 +func (err AppError) Error() string { + return err.Msg +} + // 三位数错误编码为复用http原本含义 // 五位数错误编码为应用自定义错误 // 五开头的五位数错误编码为服务器端错误,比如数据库操作失败 @@ -33,6 +54,8 @@ const ( CodeIOFailed = 50004 //CodeParamErr 各种奇奇怪怪的参数错误 CodeParamErr = 40001 + // CodeNotSet 未定错误,后续尝试从error中获取 + CodeNotSet = -1 ) // DBErr 数据库操作失败 @@ -53,6 +76,13 @@ func ParamErr(msg string, err error) Response { // Err 通用错误处理 func Err(errCode int, msg string, err error) Response { + // 如果错误code未定,则尝试从AppError中获取 + if errCode == CodeNotSet { + if appError, ok := err.(AppError); ok { + errCode = appError.Code + err = appError.RawError + } + } res := Response{ Code: errCode, Msg: msg, diff --git a/routers/controllers/file.go b/routers/controllers/file.go index df10489..faf31b4 100644 --- a/routers/controllers/file.go +++ b/routers/controllers/file.go @@ -7,11 +7,27 @@ import ( "github.com/HFO4/cloudreve/pkg/filesystem/local" "github.com/HFO4/cloudreve/pkg/serializer" "github.com/HFO4/cloudreve/pkg/util" + "github.com/HFO4/cloudreve/service/explorer" "github.com/gin-gonic/gin" "net/url" "strconv" ) +// Download 文件下载 +func Download(c *gin.Context) { + // 创建上下文 + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + var service explorer.FileDownloadService + if err := c.ShouldBindQuery(&service); err == nil { + res := service.Download(ctx, c) + c.JSON(200, res) + } else { + c.JSON(200, ErrorResponse(err)) + } +} + // FileUploadStream 本地策略流式上传 func FileUploadStream(c *gin.Context) { // 创建上下文 diff --git a/routers/router.go b/routers/router.go index 0a6a939..c1d2211 100644 --- a/routers/router.go +++ b/routers/router.go @@ -62,6 +62,8 @@ func InitRouter() *gin.Engine { { // 文件上传 file.POST("upload", controllers.FileUploadStream) + // 下载文件 + file.GET("", controllers.Download) } // 目录 diff --git a/service/explorer/file.go b/service/explorer/file.go new file mode 100644 index 0000000..1d1b0c5 --- /dev/null +++ b/service/explorer/file.go @@ -0,0 +1,33 @@ +package explorer + +import ( + "context" + "github.com/HFO4/cloudreve/pkg/filesystem" + "github.com/HFO4/cloudreve/pkg/serializer" + "github.com/gin-gonic/gin" +) + +// FileDownloadService 文件下载服务,path为文件完整路径 +type FileDownloadService struct { + Path string `form:"path" binding:"required,min=1,max=65535"` +} + +// Download 文件下载 +func (service *FileDownloadService) Download(ctx context.Context, c *gin.Context) serializer.Response { + // 创建文件系统 + fs, err := filesystem.NewFileSystemFromContext(c) + if err != nil { + return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) + + } + + _, err = fs.Download(ctx, service.Path) + + if err != nil { + return serializer.Err(serializer.CodeNotSet, err.Error(), err) + } + + return serializer.Response{ + Code: 0, + } +}