初始化
This commit is contained in:
113
server/storage/local.go
Normal file
113
server/storage/local.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// LocalEngine 本地磁盘存储引擎
|
||||
type LocalEngine struct {
|
||||
BasePath string // 存储根目录
|
||||
CDNHost string // CDN地址, 如 http://localhost:3090
|
||||
CDNPathPrefix string // CDN路径前缀, 如 /public
|
||||
}
|
||||
|
||||
// NewLocalEngine 创建本地存储引擎实例
|
||||
func NewLocalEngine(basePath string) *LocalEngine {
|
||||
os.MkdirAll(basePath, 0755)
|
||||
return &LocalEngine{BasePath: basePath}
|
||||
}
|
||||
|
||||
// NewLocalEngineWithCDN 创建带CDN配置的本地存储引擎
|
||||
func NewLocalEngineWithCDN(basePath, cdnHost, cdnPathPrefix string) *LocalEngine {
|
||||
os.MkdirAll(basePath, 0755)
|
||||
return &LocalEngine{
|
||||
BasePath: basePath,
|
||||
CDNHost: cdnHost,
|
||||
CDNPathPrefix: cdnPathPrefix,
|
||||
}
|
||||
}
|
||||
|
||||
// Upload 上传文件到本地磁盘
|
||||
func (e *LocalEngine) Upload(storageKey string, reader io.Reader, size int64) error {
|
||||
fullPath := filepath.Join(e.BasePath, storageKey)
|
||||
dir := filepath.Dir(fullPath)
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return fmt.Errorf("创建目录失败: %w", err)
|
||||
}
|
||||
|
||||
dst, err := os.Create(fullPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("创建文件失败: %w", err)
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
if _, err := io.Copy(dst, reader); err != nil {
|
||||
os.Remove(fullPath)
|
||||
return fmt.Errorf("写入文件失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Download 从本地磁盘下载文件
|
||||
func (e *LocalEngine) Download(storageKey string) (io.ReadCloser, error) {
|
||||
fullPath := filepath.Join(e.BasePath, storageKey)
|
||||
file, err := os.Open(fullPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("文件不存在: %s", storageKey)
|
||||
}
|
||||
return nil, fmt.Errorf("打开文件失败: %w", err)
|
||||
}
|
||||
return file, nil
|
||||
}
|
||||
|
||||
// Delete 从本地磁盘删除文件
|
||||
func (e *LocalEngine) Delete(storageKey string) error {
|
||||
fullPath := filepath.Join(e.BasePath, storageKey)
|
||||
err := os.Remove(fullPath)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("删除文件失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Exists 判断文件是否存在于本地磁盘
|
||||
func (e *LocalEngine) Exists(storageKey string) (bool, error) {
|
||||
fullPath := filepath.Join(e.BasePath, storageKey)
|
||||
_, err := os.Stat(fullPath)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
// GetURL 获取文件访问URL
|
||||
// 配置了CDN: http://localhost:3090/public/2026/07/02/ab/xxx.txt
|
||||
// 未配置CDN: /storage/2026/07/02/ab/xxx.txt
|
||||
func (e *LocalEngine) GetURL(storageKey string) string {
|
||||
if e.CDNHost != "" {
|
||||
// 确保路径格式正确
|
||||
prefix := strings.TrimRight(e.CDNPathPrefix, "/")
|
||||
key := strings.TrimLeft(storageKey, "/")
|
||||
return fmt.Sprintf("%s%s/%s", e.CDNHost, prefix, key)
|
||||
}
|
||||
return "/storage/" + storageKey
|
||||
}
|
||||
|
||||
// GenerateStorageKey 生成存储路径
|
||||
func GenerateStorageKey(md5, extension string) string {
|
||||
now := time.Now()
|
||||
day := now.Format("2006/01/02")
|
||||
if extension != "" {
|
||||
return fmt.Sprintf("%s/%s/%s.%s", day, md5[:2], md5, extension)
|
||||
}
|
||||
return fmt.Sprintf("%s/%s/%s", day, md5[:2], md5)
|
||||
}
|
||||
Reference in New Issue
Block a user