mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-01 22:46:38 +08:00
9a18bea324
Move storage backend configuration from startup YAML to system_config-backed runtime configuration. Add local, S3-compatible, R2, MinIO, OSS, and WebDAV backend support. Add a storage migration async task using the existing task dispatch framework. Migration target config is carried in task payload, and maintenance mode is derived from task execution state. Split upload file management and storage operations, add the admin storage configuration tab, and update migrations and Swagger docs.
75 lines
2.0 KiB
Go
75 lines
2.0 KiB
Go
// Copyright 2026 Arctel.net
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package storage
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"path"
|
|
"strings"
|
|
|
|
"github.com/studio-b12/gowebdav"
|
|
)
|
|
|
|
type webDAVBackend struct {
|
|
client *gowebdav.Client
|
|
basePath string
|
|
}
|
|
|
|
func newWebDAVBackend(cfg WebDAVConfig) (*webDAVBackend, error) {
|
|
return &webDAVBackend{
|
|
client: gowebdav.NewClient(strings.TrimRight(cfg.Endpoint, "/"), cfg.Username, cfg.Password),
|
|
basePath: strings.Trim(cfg.BasePath, "/"),
|
|
}, nil
|
|
}
|
|
|
|
func (b *webDAVBackend) Put(_ context.Context, key string, body io.Reader, size int64, _ string) (string, error) {
|
|
key = b.key(key)
|
|
if dir := path.Dir(key); dir != "." && dir != "/" {
|
|
if err := b.client.MkdirAll(dir, storageDirPerm); err != nil {
|
|
return "", fmt.Errorf("create WebDAV directory: %w", err)
|
|
}
|
|
}
|
|
if err := b.client.WriteStreamWithLength(key, body, size, storageFilePerm); err != nil {
|
|
return "", fmt.Errorf("put WebDAV object: %w", err)
|
|
}
|
|
return key, nil
|
|
}
|
|
|
|
func (b *webDAVBackend) Get(_ context.Context, key string) (*Object, error) {
|
|
key = b.key(key)
|
|
info, err := b.client.Stat(key)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("stat WebDAV object: %w", err)
|
|
}
|
|
body, err := b.client.ReadStream(key)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("get WebDAV object: %w", err)
|
|
}
|
|
contentType := defaultContentType
|
|
if typed, ok := info.(interface{ ContentType() string }); ok && typed.ContentType() != "" {
|
|
contentType = typed.ContentType()
|
|
}
|
|
return &Object{Body: body, ContentLength: info.Size(), ContentType: contentType}, nil
|
|
}
|
|
|
|
func (b *webDAVBackend) Delete(_ context.Context, key string) error {
|
|
if err := b.client.Remove(b.key(key)); err != nil {
|
|
return fmt.Errorf("delete WebDAV object: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *webDAVBackend) Test(_ context.Context) error {
|
|
if err := b.client.Connect(); err != nil {
|
|
return fmt.Errorf("connect WebDAV: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *webDAVBackend) key(key string) string {
|
|
return "/" + path.Join(b.basePath, strings.TrimLeft(key, "/"))
|
|
}
|