feat(storage): add cos support

This commit is contained in:
neo-f
2023-03-23 13:52:44 +08:00
parent 05c133a4b5
commit a56f0b8150
13 changed files with 283 additions and 90 deletions

View File

@@ -1,7 +1,6 @@
package config
import (
"net/url"
"os"
"path/filepath"
"runtime"
@@ -11,14 +10,9 @@ import (
"github.com/go-playground/validator"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spf13/cast"
"github.com/spf13/viper"
)
var ENVS = [][2]string{
{"本地测试环境", "http://localhost:8080"},
}
type Config struct {
IsLocal bool
Debug bool `mapstructure:"debug"`
@@ -36,33 +30,6 @@ type Config struct {
}
}
type ossConfig struct {
Schema string
Endpoint string
AccessID string
AccessSecret string
Region string
Bucket string
Secure bool
}
func (c *Config) GetOSSConfig() *ossConfig {
oss, err := url.Parse(c.Databases.OSS)
if err != nil {
log.Fatal().Err(err).Msg("parse oss config error")
}
accessSecret, _ := oss.User.Password()
return &ossConfig{
Schema: oss.Scheme,
Endpoint: oss.Host,
AccessID: oss.User.Username(),
AccessSecret: accessSecret,
Region: oss.Query().Get("region"),
Bucket: oss.Query().Get("bucket"),
Secure: cast.ToBool(oss.Query().Get("secure")),
}
}
var (
c *Config
once sync.Once

View File

@@ -23,3 +23,7 @@ const (
LogTagStaffID = "staff_id"
LogTagTraceID = "trace_id"
)
var ENVS = [][2]string{
{"本地测试环境", "http://localhost:8080"},
}

View File

@@ -3,7 +3,6 @@ package model
import (
"context"
"net/url"
"octopus/internal/config"
"octopus/internal/dal"
"time"
@@ -37,15 +36,14 @@ type Doc struct {
IsDeletable bool `gorm:"column:is_deletable;type:boolean;not null;default:true"` // 是否允许被删除
IsEditable bool `gorm:"column:is_editable;type:boolean;not null;default:true"` // 是否允许编辑名称
FolderID string `gorm:"column:folder_id;type:varchar;index:idx_folder_id"` // 文件夹ID
OSSObjectID string `gorm:"column:oss_object_id;type:varchar"` // OSS Object ID
ObjectName string `gorm:"column:object_name;type:varchar"` // 对象存储中对应的object_name
CreatedBy string `gorm:"column:created_by;type:varchar;not null"` // 创建人
Folder *DocFolder `gorm:"foreignKey:FolderID;references:ID"`
}
func (df *Doc) PresignedURL(ctx context.Context) (*url.URL, error) {
bucket := config.Get().GetOSSConfig().Bucket
return dal.GetMinio().PresignedGetObject(ctx, bucket, df.OSSObjectID, time.Hour, nil)
return dal.GetStorage().PresignedGetObject(ctx, df.ObjectName, time.Hour)
}
func (*Doc) TableName() string {

View File

@@ -1,50 +0,0 @@
package dal
import (
"net/url"
"octopus/internal/config"
"sync"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"github.com/rs/zerolog/log"
// pb "github.com/qdrant/go-client/qdrant"
)
var (
ossOnce sync.Once
ossInstance *minio.Client
)
func GetMinio() *minio.Client {
ossOnce.Do(initMinio)
return ossInstance
}
func initMinio() {
log.Info().Msg("loading minio configs")
ossConfig, err := url.Parse(config.Get().Databases.OSS)
if err != nil {
log.Fatal().Err(err).Msg("parse oss config error")
}
accessSecret, _ := ossConfig.User.Password()
// defaultConfig := &model.StorageConfig{
// Schema: ossConfig.Scheme,
// Endpoint: ossConfig.Host,
// AccessID: ossConfig.User.Username(),
// AccessSecret: accessSecret,
// Bucket: ossConfig.Query().Get("bucket"),
// Region: ossConfig.Query().Get("region"),
// Secure: cast.ToBool(ossConfig.Query().Get("secure")),
// }
minioClient, err := minio.New(ossConfig.Host, &minio.Options{
Creds: credentials.NewStaticV4(ossConfig.User.Username(), accessSecret, ""),
Secure: false,
})
if err != nil {
log.Fatal().Msgf("minio client init error: %v", err)
}
ossInstance = minioClient
}

31
internal/dal/storage.go Normal file
View File

@@ -0,0 +1,31 @@
package dal
import (
"octopus/internal/config"
"octopus/pkg/storage"
"sync"
"github.com/rs/zerolog/log"
// pb "github.com/qdrant/go-client/qdrant"
)
var (
storageOnce sync.Once
storageInstance storage.ObjectStorage
)
func GetStorage() storage.ObjectStorage {
storageOnce.Do(initMinio)
return storageInstance
}
func initMinio() {
log.Info().Msg("loading minio configs")
s, err := storage.NewObjectStorage(config.Get().Databases.OSS)
if err != nil {
log.Fatal().Msgf("storage client init failed: %v", err)
}
storageInstance = s
}

View File

@@ -29,6 +29,14 @@ func RegisterDocRouter(app *soda.Soda) {
SetJSONRequestBody(schema.UpdateDoc{}).
AddJSONResponse(200, schema.Doc{}).OK()
// get presigned url for tmp file upload
app.Get("/docs/upload-url", nil).
AddTags("文档管理").
SetSummary("获取临时上传文件用的预签名URL").
AddJWTSecurity(JWTRequired).
SetParameters(schema.CreateUploadURL{}).
AddJSONResponse(200, schema.UploadURL{}).OK()
app.Delete("/docs/:id", nil).
AddTags("文档管理").
SetSummary("获取文档列表").

View File

@@ -1,6 +1,7 @@
package schema
import (
"net/url"
"octopus/pkg/tools"
"time"
@@ -63,8 +64,9 @@ type DocID struct {
}
type CreateDoc struct {
Name string `json:"name" validate:"required" oai:"description=文档名称"`
FolderID string `json:"folder_id" validate:"required" oai:"description=归属文件夹ID"`
Name string `json:"name" validate:"required" oai:"description=文档名称"`
ObjectName string `json:"object_name" validate:"required" oai:"description=对象存储中对应的文档对象名称"`
FolderID string `json:"folder_id" validate:"required" oai:"description=归属文件夹ID"`
}
type UpdateDoc struct {
@@ -104,3 +106,12 @@ func (q *ListDocQuery) Validate() error {
}
return nil
}
type CreateUploadURL struct {
FileName string `query:"file_name" validate:"required" oai:"description=上传文件名"`
}
type UploadURL struct {
URL url.URL `json:"url" oai:"description=生成的预签名上传URL"`
ObjectName string `json:"object_name" oai:"description=上传文件名"`
}