Cloudreve/models/policy.go

210 lines
5.6 KiB
Go
Raw Normal View History

2019-11-14 01:18:10 -05:00
package model
import (
2019-12-09 02:20:02 -05:00
"encoding/gob"
2019-11-14 01:18:10 -05:00
"encoding/json"
2019-12-05 04:01:14 -05:00
"github.com/HFO4/cloudreve/pkg/cache"
2019-11-17 00:50:14 -05:00
"github.com/HFO4/cloudreve/pkg/util"
2019-11-14 01:18:10 -05:00
"github.com/jinzhu/gorm"
"net/url"
2020-01-04 03:21:43 -05:00
"path"
2019-11-17 00:50:14 -05:00
"strconv"
"time"
2019-11-14 01:18:10 -05:00
)
// Policy 存储策略
type Policy struct {
// 表字段
gorm.Model
Name string
Type string
Server string
BucketName string
IsPrivate bool
BaseURL string
AccessKey string `gorm:"size:512"`
SecretKey string `gorm:"size:512"`
MaxSize uint64
AutoRename bool
DirNameRule string
FileNameRule string
IsOriginLinkEnable bool
Options string `gorm:"size:4096"`
// 数据库忽略字段
OptionsSerialized PolicyOption `gorm:"-"`
}
// PolicyOption 非公有的存储策略属性
type PolicyOption struct {
2020-01-18 01:08:43 -05:00
// Upyun访问Token
Token string `json:"token"`
// 允许的文件扩展名
FileType []string `json:"file_type"`
// MimeType
MimeType string `json:"mimetype"`
2020-01-18 23:52:36 -05:00
// OdRedirect Onedrive重定向地址
OdRedirect string `json:"od_redirect,omitempty"`
2019-11-14 01:18:10 -05:00
}
2019-12-09 02:20:02 -05:00
func init() {
// 注册缓存用到的复杂结构
gob.Register(Policy{})
}
2019-11-14 01:18:10 -05:00
// GetPolicyByID 用ID获取存储策略
func GetPolicyByID(ID interface{}) (Policy, error) {
2019-11-30 02:09:56 -05:00
// 尝试读取缓存
2019-12-05 04:01:14 -05:00
cacheKey := "policy_" + strconv.Itoa(int(ID.(uint)))
2019-12-09 02:20:02 -05:00
if policy, ok := cache.Get(cacheKey); ok {
2019-12-05 04:01:14 -05:00
return policy.(Policy), nil
2019-11-30 02:09:56 -05:00
}
2019-11-14 01:18:10 -05:00
var policy Policy
result := DB.First(&policy, ID)
2019-11-30 02:09:56 -05:00
// 写入缓存
if result.Error == nil {
_ = cache.Set(cacheKey, policy, -1)
2019-11-30 02:09:56 -05:00
}
2019-11-14 01:18:10 -05:00
return policy, result.Error
}
2019-11-30 02:09:56 -05:00
// AfterFind 找到存储策略后的钩子
2019-11-14 01:18:10 -05:00
func (policy *Policy) AfterFind() (err error) {
2019-11-30 02:09:56 -05:00
// 解析存储策略设置到OptionsSerialized
2019-11-14 01:18:10 -05:00
err = json.Unmarshal([]byte(policy.Options), &policy.OptionsSerialized)
if policy.OptionsSerialized.FileType == nil {
policy.OptionsSerialized.FileType = []string{}
}
2019-11-14 01:18:10 -05:00
return err
}
// BeforeSave Save策略前的钩子
func (policy *Policy) BeforeSave() (err error) {
err = policy.SerializeOptions()
return err
}
//SerializeOptions 将序列后的Option写入到数据库字段
func (policy *Policy) SerializeOptions() (err error) {
optionsValue, err := json.Marshal(&policy.OptionsSerialized)
policy.Options = string(optionsValue)
return err
}
2019-11-17 00:50:14 -05:00
// GeneratePath 生成存储文件的路径
2020-01-04 03:21:43 -05:00
func (policy *Policy) GeneratePath(uid uint, origin string) string {
2019-11-17 00:50:14 -05:00
dirRule := policy.DirNameRule
replaceTable := map[string]string{
"{randomkey16}": util.RandStringRunes(16),
"{randomkey8}": util.RandStringRunes(8),
"{timestamp}": strconv.FormatInt(time.Now().Unix(), 10),
"{uid}": strconv.Itoa(int(uid)),
"{datetime}": time.Now().Format("20060102150405"),
"{date}": time.Now().Format("20060102"),
2020-01-04 03:21:43 -05:00
"{path}": origin + "/",
2019-11-17 00:50:14 -05:00
}
dirRule = util.Replace(replaceTable, dirRule)
2020-01-04 03:21:43 -05:00
return path.Clean(dirRule)
2019-11-17 00:50:14 -05:00
}
// GenerateFileName 生成存储文件名
func (policy *Policy) GenerateFileName(uid uint, origin string) string {
2019-11-18 06:09:56 -05:00
// 未开启自动重命名时,直接返回原始文件名
if !policy.AutoRename {
2020-01-16 00:36:13 -05:00
return policy.getOriginNameRule(origin)
2019-11-18 06:09:56 -05:00
}
2019-11-17 00:50:14 -05:00
fileRule := policy.FileNameRule
replaceTable := map[string]string{
"{randomkey16}": util.RandStringRunes(16),
"{randomkey8}": util.RandStringRunes(8),
"{timestamp}": strconv.FormatInt(time.Now().Unix(), 10),
"{uid}": strconv.Itoa(int(uid)),
"{datetime}": time.Now().Format("20060102150405"),
"{date}": time.Now().Format("20060102"),
}
2020-01-16 00:36:13 -05:00
replaceTable["{originname}"] = policy.getOriginNameRule(origin)
fileRule = util.Replace(replaceTable, fileRule)
return fileRule
}
func (policy Policy) getOriginNameRule(origin string) string {
2019-11-17 00:50:14 -05:00
// 部分存储策略可以使用{origin}代表原始文件名
2020-01-15 03:03:23 -05:00
if origin == "" {
// 如果上游未传回原始文件名,则使用占位符,让云存储端替换
switch policy.Type {
case "qiniu":
// 七牛会将$(fname)自动替换为原始文件名
2020-01-16 00:36:13 -05:00
return "$(fname)"
2020-01-15 03:03:23 -05:00
case "local", "remote":
2020-01-16 00:36:13 -05:00
return origin
2020-01-15 03:03:23 -05:00
case "oss":
// OSS会将${filename}自动替换为原始文件名
2020-01-16 00:36:13 -05:00
return "${filename}"
2020-01-15 03:03:23 -05:00
case "upyun":
// Upyun会将{filename}{.suffix}自动替换为原始文件名
2020-01-16 00:36:13 -05:00
return "{filename}{.suffix}"
2020-01-15 03:03:23 -05:00
}
2019-11-17 00:50:14 -05:00
}
2020-01-16 00:36:13 -05:00
return origin
2019-11-17 00:50:14 -05:00
}
// IsDirectlyPreview 返回此策略下文件是否可以直接预览(不需要重定向)
func (policy *Policy) IsDirectlyPreview() bool {
return policy.Type == "local"
}
2020-01-14 21:14:15 -05:00
// IsPathGenerateNeeded 返回此策略是否需要在生成上传凭证时生成存储路径
func (policy *Policy) IsPathGenerateNeeded() bool {
return policy.Type != "remote"
}
2020-01-16 21:52:43 -05:00
// IsThumbGenerateNeeded 返回此策略是否需要在上传后生成缩略图
func (policy *Policy) IsThumbGenerateNeeded() bool {
return policy.Type == "local"
}
// GetUploadURL 获取文件上传服务API地址
func (policy *Policy) GetUploadURL() string {
server, err := url.Parse(policy.Server)
if err != nil {
return policy.Server
}
var controller *url.URL
switch policy.Type {
case "local":
controller, _ = url.Parse("/api/v3/file/upload")
case "remote":
controller, _ = url.Parse("/api/v3/slave/upload")
2020-01-16 00:36:13 -05:00
case "oss":
return policy.BaseURL
case "upyun":
return "http://v0.api.upyun.com/" + policy.BucketName
default:
controller, _ = url.Parse("")
}
return server.ResolveReference(controller).String()
}
2020-01-18 23:52:36 -05:00
// UpdateAccessKey 更新 AccessKey
// TODO 测试
func (policy *Policy) UpdateAccessKey(key string) error {
policy.AccessKey = key
err := DB.Save(policy).Error
policy.ClearCache()
return err
}
// ClearCache 清空policy缓存
func (policy *Policy) ClearCache() {
cache.Deletes([]string{strconv.FormatUint(uint64(policy.ID), 10)}, "policy_")
}