supports local file system object storage and use it as the default avatar provider

This commit is contained in:
MaysWind
2024-07-27 23:29:18 +08:00
parent 731b6e8bad
commit 2e04affb00
26 changed files with 858 additions and 29 deletions
+68
View File
@@ -0,0 +1,68 @@
package storage
import (
"io"
"os"
"path/filepath"
"github.com/mayswind/ezbookkeeping/pkg/settings"
"github.com/mayswind/ezbookkeeping/pkg/utils"
)
// LocalFileSystemObjectStorage represents local file system object storage
type LocalFileSystemObjectStorage struct {
rootPath string
}
// NewLocalFileSystemObjectStorage returns a local file system object storage
func NewLocalFileSystemObjectStorage(config *settings.Config, pathPrefix string) (*LocalFileSystemObjectStorage, error) {
storage := &LocalFileSystemObjectStorage{
rootPath: filepath.Join(config.LocalFileSystemPath, pathPrefix),
}
if err := os.MkdirAll(storage.rootPath, os.ModePerm); err != nil {
return nil, err
}
return storage, nil
}
// Exists returns whether the file exists
func (s *LocalFileSystemObjectStorage) Exists(path string) (bool, error) {
return utils.IsExists(s.getFinalPath(path))
}
// Read returns the object instance according to specified the file path
func (s *LocalFileSystemObjectStorage) Read(path string) (ObjectInStorage, error) {
return os.Open(s.getFinalPath(path))
}
// Save returns whether save the object instance successfully
func (s *LocalFileSystemObjectStorage) Save(path string, object ObjectInStorage) error {
finalPath := s.getFinalPath(path)
if err := os.MkdirAll(filepath.Dir(finalPath), os.ModePerm); err != nil {
return err
}
targetFile, err := os.Create(finalPath)
if err != nil {
return err
}
defer targetFile.Close()
_, err = io.Copy(targetFile, object)
return err
}
// Delete returns whether delete the object according to specified the file path successfully
func (s *LocalFileSystemObjectStorage) Delete(path string) error {
return os.Remove(s.getFinalPath(path))
}
func (s *LocalFileSystemObjectStorage) getFinalPath(path string) string {
return filepath.Join(s.rootPath, path)
}
+11
View File
@@ -0,0 +1,11 @@
package storage
import (
"io"
)
// ObjectInStorage represents the object instance in the storage
type ObjectInStorage interface {
io.ReadCloser
io.Seeker
}
+9
View File
@@ -0,0 +1,9 @@
package storage
// ObjectStorage represents an object storage to store file object
type ObjectStorage interface {
Exists(path string) (bool, error)
Read(path string) (ObjectInStorage, error)
Save(path string, object ObjectInStorage) error
Delete(path string) error
}
+56
View File
@@ -0,0 +1,56 @@
package storage
import (
"fmt"
"github.com/mayswind/ezbookkeeping/pkg/errs"
"github.com/mayswind/ezbookkeeping/pkg/settings"
)
const avatarPathPrefix = "avatar"
// StorageContainer contains the current object storage
type StorageContainer struct {
AvatarCurrentStorage ObjectStorage
}
// Initialize a object storage container singleton instance
var (
Container = &StorageContainer{}
)
// InitializeStorageContainer initializes the current object storage according to the config
func InitializeStorageContainer(config *settings.Config) error {
if config.StorageType == settings.LocalFileSystemObjectStorageType {
storage, err := NewLocalFileSystemObjectStorage(config, avatarPathPrefix)
Container.AvatarCurrentStorage = storage
return err
}
return errs.ErrInvalidStorageType
}
// ExistsAvatar returns whether the user avatar exists from the current object storage
func (s *StorageContainer) ExistsAvatar(uid int64, fileExtension string) (bool, error) {
return s.AvatarCurrentStorage.Exists(s.getUserAvatarPath(uid, fileExtension))
}
// ReadAvatar returns the user avatar from the current object storage
func (s *StorageContainer) ReadAvatar(uid int64, fileExtension string) (ObjectInStorage, error) {
return s.AvatarCurrentStorage.Read(s.getUserAvatarPath(uid, fileExtension))
}
// SaveAvatar returns whether save the user avatar into the current object storage successfully
func (s *StorageContainer) SaveAvatar(uid int64, object ObjectInStorage, fileExtension string) error {
return s.AvatarCurrentStorage.Save(s.getUserAvatarPath(uid, fileExtension), object)
}
// DeleteAvatar returns whether delete the user avatar from the current object storage successfully
func (s *StorageContainer) DeleteAvatar(uid int64, fileExtension string) error {
return s.AvatarCurrentStorage.Delete(s.getUserAvatarPath(uid, fileExtension))
}
func (s *StorageContainer) getUserAvatarPath(uid int64, fileExtension string) string {
return fmt.Sprintf("%d.%s", uid, fileExtension)
}