package storage import ( "context" "fmt" "io" "os" "path/filepath" "github.com/youruser/base/internal/config" ) type LocalStorage struct { rootDir string } func NewLocalStorage(cfg config.LocalStorageConfig) (*LocalStorage, error) { rootDir := cfg.RootDir if rootDir == "" { rootDir = "./uploads" } if err := os.MkdirAll(rootDir, 0755); err != nil { return nil, fmt.Errorf("failed to create upload dir: %w", err) } return &LocalStorage{rootDir: rootDir}, nil } func (s *LocalStorage) Upload(ctx context.Context, key string, reader io.Reader, size int64, contentType string) error { fullPath := filepath.Join(s.rootDir, key) if err := os.MkdirAll(filepath.Dir(fullPath), 0755); err != nil { return fmt.Errorf("failed to create directory: %w", err) } file, err := os.Create(fullPath) if err != nil { return fmt.Errorf("failed to create file: %w", err) } defer file.Close() if _, err := io.Copy(file, reader); err != nil { return fmt.Errorf("failed to write file: %w", err) } return nil } func (s *LocalStorage) Delete(ctx context.Context, key string) error { fullPath := filepath.Join(s.rootDir, key) if err := os.Remove(fullPath); err != nil && !os.IsNotExist(err) { return fmt.Errorf("failed to delete file: %w", err) } return nil } func (s *LocalStorage) GetURL(ctx context.Context, key string) (string, error) { return "local://" + key, nil } func (s *LocalStorage) Exists(ctx context.Context, key string) (bool, error) { fullPath := filepath.Join(s.rootDir, key) _, err := os.Stat(fullPath) if err == nil { return true, nil } if os.IsNotExist(err) { return false, nil } return false, err } // GetFilePath returns the full filesystem path for a key (used by download handler). func (s *LocalStorage) GetFilePath(key string) string { return filepath.Join(s.rootDir, key) }