addui
This commit is contained in:
115
internal/infrastructure/external/storage/local_file_storage_service.go
vendored
Normal file
115
internal/infrastructure/external/storage/local_file_storage_service.go
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// LocalFileStorageService 本地文件存储服务
|
||||
type LocalFileStorageService struct {
|
||||
basePath string
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// LocalFileStorageConfig 本地文件存储配置
|
||||
type LocalFileStorageConfig struct {
|
||||
BasePath string `yaml:"base_path"`
|
||||
}
|
||||
|
||||
// NewLocalFileStorageService 创建本地文件存储服务
|
||||
func NewLocalFileStorageService(basePath string, logger *zap.Logger) *LocalFileStorageService {
|
||||
// 确保基础路径存在
|
||||
if err := os.MkdirAll(basePath, 0755); err != nil {
|
||||
logger.Error("创建基础存储目录失败", zap.Error(err), zap.String("path", basePath))
|
||||
}
|
||||
|
||||
return &LocalFileStorageService{
|
||||
basePath: basePath,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// StoreFile 存储文件
|
||||
func (s *LocalFileStorageService) StoreFile(ctx context.Context, file io.Reader, filename string) (string, error) {
|
||||
// 构建完整文件路径
|
||||
fullPath := filepath.Join(s.basePath, filename)
|
||||
|
||||
// 确保目录存在
|
||||
dir := filepath.Dir(fullPath)
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
s.logger.Error("创建目录失败", zap.Error(err), zap.String("dir", dir))
|
||||
return "", fmt.Errorf("创建目录失败: %w", err)
|
||||
}
|
||||
|
||||
// 创建文件
|
||||
dst, err := os.Create(fullPath)
|
||||
if err != nil {
|
||||
s.logger.Error("创建文件失败", zap.Error(err), zap.String("path", fullPath))
|
||||
return "", fmt.Errorf("创建文件失败: %w", err)
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
// 复制文件内容
|
||||
if _, err := io.Copy(dst, file); err != nil {
|
||||
s.logger.Error("写入文件失败", zap.Error(err), zap.String("path", fullPath))
|
||||
// 删除部分写入的文件
|
||||
_ = os.Remove(fullPath)
|
||||
return "", fmt.Errorf("写入文件失败: %w", err)
|
||||
}
|
||||
|
||||
s.logger.Info("文件存储成功", zap.String("path", fullPath))
|
||||
return fullPath, nil
|
||||
}
|
||||
|
||||
// StoreMultipartFile 存储multipart文件
|
||||
func (s *LocalFileStorageService) StoreMultipartFile(ctx context.Context, file *multipart.FileHeader, filename string) (string, error) {
|
||||
src, err := file.Open()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("打开上传文件失败: %w", err)
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
return s.StoreFile(ctx, src, filename)
|
||||
}
|
||||
|
||||
// GetFileURL 获取文件URL
|
||||
func (s *LocalFileStorageService) GetFileURL(ctx context.Context, filePath string) (string, error) {
|
||||
// 检查文件是否存在
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
return "", fmt.Errorf("文件不存在: %s", filePath)
|
||||
}
|
||||
|
||||
// 返回文件路径(在实际应用中,这里应该返回可访问的URL)
|
||||
return filePath, nil
|
||||
}
|
||||
|
||||
// DeleteFile 删除文件
|
||||
func (s *LocalFileStorageService) DeleteFile(ctx context.Context, filePath string) error {
|
||||
if err := os.Remove(filePath); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// 文件不存在,不视为错误
|
||||
return nil
|
||||
}
|
||||
s.logger.Error("删除文件失败", zap.Error(err), zap.String("path", filePath))
|
||||
return fmt.Errorf("删除文件失败: %w", err)
|
||||
}
|
||||
|
||||
s.logger.Info("文件删除成功", zap.String("path", filePath))
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetFileReader 获取文件读取器
|
||||
func (s *LocalFileStorageService) GetFileReader(ctx context.Context, filePath string) (io.ReadCloser, error) {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("打开文件失败: %w", err)
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
||||
110
internal/infrastructure/external/storage/local_file_storage_service_impl.go
vendored
Normal file
110
internal/infrastructure/external/storage/local_file_storage_service_impl.go
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// LocalFileStorageServiceImpl 本地文件存储服务实现
|
||||
type LocalFileStorageServiceImpl struct {
|
||||
basePath string
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewLocalFileStorageServiceImpl 创建本地文件存储服务实现
|
||||
func NewLocalFileStorageServiceImpl(basePath string, logger *zap.Logger) *LocalFileStorageServiceImpl {
|
||||
// 确保基础路径存在
|
||||
if err := os.MkdirAll(basePath, 0755); err != nil {
|
||||
logger.Error("创建基础存储目录失败", zap.Error(err), zap.String("path", basePath))
|
||||
}
|
||||
|
||||
return &LocalFileStorageServiceImpl{
|
||||
basePath: basePath,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// StoreFile 存储文件
|
||||
func (s *LocalFileStorageServiceImpl) StoreFile(ctx context.Context, file io.Reader, filename string) (string, error) {
|
||||
// 构建完整文件路径
|
||||
fullPath := filepath.Join(s.basePath, filename)
|
||||
|
||||
// 确保目录存在
|
||||
dir := filepath.Dir(fullPath)
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
s.logger.Error("创建目录失败", zap.Error(err), zap.String("dir", dir))
|
||||
return "", fmt.Errorf("创建目录失败: %w", err)
|
||||
}
|
||||
|
||||
// 创建文件
|
||||
dst, err := os.Create(fullPath)
|
||||
if err != nil {
|
||||
s.logger.Error("创建文件失败", zap.Error(err), zap.String("path", fullPath))
|
||||
return "", fmt.Errorf("创建文件失败: %w", err)
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
// 复制文件内容
|
||||
if _, err := io.Copy(dst, file); err != nil {
|
||||
s.logger.Error("写入文件失败", zap.Error(err), zap.String("path", fullPath))
|
||||
// 删除部分写入的文件
|
||||
_ = os.Remove(fullPath)
|
||||
return "", fmt.Errorf("写入文件失败: %w", err)
|
||||
}
|
||||
|
||||
s.logger.Info("文件存储成功", zap.String("path", fullPath))
|
||||
return fullPath, nil
|
||||
}
|
||||
|
||||
// StoreMultipartFile 存储multipart文件
|
||||
func (s *LocalFileStorageServiceImpl) StoreMultipartFile(ctx context.Context, file *multipart.FileHeader, filename string) (string, error) {
|
||||
src, err := file.Open()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("打开上传文件失败: %w", err)
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
return s.StoreFile(ctx, src, filename)
|
||||
}
|
||||
|
||||
// GetFileURL 获取文件URL
|
||||
func (s *LocalFileStorageServiceImpl) GetFileURL(ctx context.Context, filePath string) (string, error) {
|
||||
// 检查文件是否存在
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
return "", fmt.Errorf("文件不存在: %s", filePath)
|
||||
}
|
||||
|
||||
// 返回文件路径(在实际应用中,这里应该返回可访问的URL)
|
||||
return filePath, nil
|
||||
}
|
||||
|
||||
// DeleteFile 删除文件
|
||||
func (s *LocalFileStorageServiceImpl) DeleteFile(ctx context.Context, filePath string) error {
|
||||
if err := os.Remove(filePath); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// 文件不存在,不视为错误
|
||||
return nil
|
||||
}
|
||||
s.logger.Error("删除文件失败", zap.Error(err), zap.String("path", filePath))
|
||||
return fmt.Errorf("删除文件失败: %w", err)
|
||||
}
|
||||
|
||||
s.logger.Info("文件删除成功", zap.String("path", filePath))
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetFileReader 获取文件读取器
|
||||
func (s *LocalFileStorageServiceImpl) GetFileReader(ctx context.Context, filePath string) (io.ReadCloser, error) {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("打开文件失败: %w", err)
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
||||
Reference in New Issue
Block a user