Documentation
¶
Overview ¶
providers.go 云厂商对象存储预设(S3 兼容协议)。
腾讯云 COS / 阿里云 OSS / 百度云 BOS / 金山云 KS3 / 华为云 OBS / AWS S3 均提供 S3 兼容端点,统一经 s3 驱动(minio-go SigV4)读写; 本表负责三件事:
- endpoint 推导:用户只填 region(endpoint 留空时按厂商模板生成)
- path_style 缺省:各厂商均为 virtual-host 风格(MinIO/自建才用 path style)
- type 白名单与展示名
Index ¶
- Constants
- Variables
- func BuildAndProbe(ctx context.Context, cfg *StorageConfig) error
- func IsCloudProviderType(t StorageType) bool
- func ProbeConfig(ctx context.Context, cfg *StorageConfig) error
- func ResolveCloudProvider(t StorageType, region, bucket, accessKey, secretKey, endpoint string, ...) (map[string]string, error)
- type FileOperationResult
- type ProviderPreset
- type RemoteObjectInfo
- type StorageConfig
- type StorageInterface
- type StorageService
- func (s *StorageService) CleanChunks(ctx context.Context, uploadID string) error
- func (s *StorageService) DataPath() string
- func (s *StorageService) DeleteFile(ctx context.Context, filePath string) error
- func (s *StorageService) EffectiveType() StorageType
- func (s *StorageService) FileExists(ctx context.Context, filePath string) bool
- func (s *StorageService) GetFile(ctx context.Context, filePath string) ([]byte, error)
- func (s *StorageService) GetFileReader(ctx context.Context, filePath string) (io.ReadCloser, int64, error)
- func (s *StorageService) GetFileReaderRange(ctx context.Context, filePath string, start, length int64) (io.ReadCloser, int64, error)
- func (s *StorageService) GetFileSize(ctx context.Context, filePath string) (int64, error)
- func (s *StorageService) GetFileURL(ctx context.Context, filePath string) (string, error)
- func (s *StorageService) HeadObject(ctx context.Context, objectKey string) (int64, string, error)
- func (s *StorageService) InitError() error
- func (s *StorageService) ListRemoteObjects(ctx context.Context, prefix string) ([]RemoteObjectInfo, error)
- func (s *StorageService) LocalAbsPath(rel string) string
- func (s *StorageService) MergeChunks(ctx context.Context, uploadID string, totalChunks int, savePath string) error
- func (s *StorageService) PresignGetURL(ctx context.Context, objectKey string, expire time.Duration) (string, error)
- func (s *StorageService) PresignPutURL(ctx context.Context, objectKey string, expire time.Duration) (string, error)
- func (s *StorageService) Reload(config *StorageConfig) error
- func (s *StorageService) SaveBytes(ctx context.Context, savePath string, data []byte) error
- func (s *StorageService) SaveChunk(ctx context.Context, uploadID string, chunkIndex int, data []byte) error
- func (s *StorageService) SaveFile(ctx context.Context, file *multipart.FileHeader, savePath string) (*FileOperationResult, error)
- func (s *StorageService) SaveStream(ctx context.Context, savePath string, r io.Reader, expectedSize int64) (int64, error)
- func (s *StorageService) StatFile(ctx context.Context, filePath string) (int64, error)
- type StorageType
- type StoredFileEntry
Constants ¶
const ( StorageTypeOSS = StorageType("oss") StorageTypeCOS = StorageType("cos") StorageTypeBOS = StorageType("bos") StorageTypeKS3 = StorageType("ks3") StorageTypeOBS = StorageType("obs") )
Variables ¶
var ErrPresignUnsupported = errors.New("presign direct transfer not supported by current storage backend")
ErrPresignUnsupported 当前存储后端不支持真预签名直传/直下(local/webdav 走服务端中转)。
var ErrRangeUnsupported = opendal.ErrRangeUnsupported
ErrRangeUnsupported 当前存储后端不支持按字节区间读取(Range 下载/断点续传)。 转发 opendal.ErrRangeUnsupported,调用方用 errors.Is 判断后回退全量流。
Functions ¶
func BuildAndProbe ¶
func BuildAndProbe(ctx context.Context, cfg *StorageConfig) error
BuildAndProbe 构造 Operator 并做认证级探测(管理端「测试连接」用)。 local 返回 nil operator(无需探测)。
func IsCloudProviderType ¶
func IsCloudProviderType(t StorageType) bool
IsCloudProviderType type 是否为受支持的云厂商(S3 兼容)
func ProbeConfig ¶
func ProbeConfig(ctx context.Context, cfg *StorageConfig) error
ProbeConfig 认证级验证存储配置(管理端切换/保存前调用)。 s3/webdav:凭据+可达性;云厂商(oss/cos/bos/ks3/obs):凭据有效且桶存在; local:路径可创建可写。 注意:云厂商类型必须显式列入下方 case——ConfigFromConf 归一后 Type 仍是 厂商名(cos 等),若落入 default 会被当 local 只探本地路径,坏配置静默上线 (2026-10-05 215 实测:不存在的桶 Probe 照样通过,上传全挂)。
func ResolveCloudProvider ¶
func ResolveCloudProvider(t StorageType, region, bucket, accessKey, secretKey, endpoint string, useSSL, pathStyle *bool) (map[string]string, error)
ResolveCloudProvider 把厂商配置归一为 S3 驱动 options。 返回 (options, error);endpoint 由显式配置或 region 推导得出。
Types ¶
type FileOperationResult ¶
type FileOperationResult struct {
Success bool `json:"success"`
Message string `json:"message,omitempty"`
Error error `json:"-"`
FilePath string `json:"file_path,omitempty"`
FileSize int64 `json:"file_size,omitempty"`
FileHash string `json:"file_hash,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
Timestamp time.Time `json:"timestamp"`
}
FileOperationResult 文件操作结果
type ProviderPreset ¶
type ProviderPreset struct {
// DeriveEndpoint 按 region 推导 S3 兼容端点(不带协议前缀;返回空表示必须显式配置)
DeriveEndpoint func(region string) string
// DefaultPathStyle 各厂商均为 virtual-host;MinIO/自建 S3 才默认 path style
DefaultPathStyle bool
// DisplayName 运维展示名
DisplayName string
}
ProviderPreset 厂商预设
type RemoteObjectInfo ¶
RemoteObjectInfo 远端对象列举项(presign 孤儿清理用)。
type StorageConfig ¶
type StorageConfig struct {
Type StorageType
DataPath string // 本地存储路径
BaseURL string // 基础URL
// S3 配置
Endpoint string
AccessKey string
SecretKey string
Bucket string
Region string
UseSSL bool
PathStyle bool // 路径风格寻址(MinIO/Ceph 自建场景)
// WebDAV 配置
WebDAVURL string
WebDAVUsername string
WebDAVPassword string
// Root 远端根目录(webdav:所有对象挂其下,避免绝对路径写入;空 = "pigeonbox")
Root string
// FTP/SFTP/Azure Blob/HDFS/OneDrive 配置(存储驱动扩展;指针复用 conf 结构)
FTP *conf.FTPConfig
SFTP *conf.SFTPConfig
Azure *conf.AzureBlobConfig
HDFS *conf.HDFSConfig
OneDrive *conf.OneDriveConfig
}
StorageConfig 存储配置
func ConfigFromConf ¶
func ConfigFromConf(c *conf.StorageConfig, baseURL string) *StorageConfig
ConfigFromConf 把 conf 的存储配置映射为 StorageConfig(bootstrap 与管理端切换共用)。
func (*StorageConfig) ToConf ¶
func (c *StorageConfig) ToConf() *conf.StorageConfig
ToConf 反向映射(运行时切换后持久化回 conf.StorageConfig 形态)。
type StorageInterface ¶
type StorageInterface interface {
// 基础操作
SaveFile(ctx context.Context, file *multipart.FileHeader, savePath string) (*FileOperationResult, error)
DeleteFile(ctx context.Context, filePath string) error
GetFile(ctx context.Context, filePath string) ([]byte, error)
FileExists(ctx context.Context, filePath string) bool
// 流式写入(本地导入/服务端拷贝用;返回写入字节数)
SaveStream(ctx context.Context, savePath string, r io.Reader, expectedSize int64) (int64, error)
// 分片操作
SaveChunk(ctx context.Context, uploadID string, chunkIndex int, data []byte) error
MergeChunks(ctx context.Context, uploadID string, totalChunks int, savePath string) error
CleanChunks(ctx context.Context, uploadID string) error
// 工具方法
GetFileSize(ctx context.Context, filePath string) (int64, error)
GetFileURL(ctx context.Context, filePath string) (string, error)
// 流式下载方法
GetFileReader(ctx context.Context, filePath string) (io.ReadCloser, int64, error)
}
StorageInterface 存储接口(简化版)
type StorageService ¶
type StorageService struct {
// contains filtered or unexported fields
}
StorageService 存储服务。 local 走本地文件系统(实现与拆分前完全一致);s3/webdav 经 opendal.Operator 分派到对应驱动。管理端在线切换后端时通过 Reload 热替换(在途请求持旧后端完成)。
func NewStorageService ¶
func NewStorageService(config *StorageConfig) *StorageService
NewStorageService 创建存储服务(兼容入口)。 远端后端配置非法时降级 local 并记录原因(InitError 可查),与拆分前行为兼容。
func NewStorageServiceE ¶
func NewStorageServiceE(config *StorageConfig) (*StorageService, error)
NewStorageServiceE 创建存储服务;远端后端配置非法时返回错误(bootstrap 用, 失败要显式暴露而不是静默落本地盘)。
func (*StorageService) CleanChunks ¶
func (s *StorageService) CleanChunks(ctx context.Context, uploadID string) error
CleanChunks 清理分片
func (*StorageService) DataPath ¶
func (s *StorageService) DataPath() string
DataPath 返回本地存储根目录(分片临时区;远端模式下仍承载合并副本)。
func (*StorageService) DeleteFile ¶
func (s *StorageService) DeleteFile(ctx context.Context, filePath string) error
DeleteFile 删除文件
func (*StorageService) EffectiveType ¶
func (s *StorageService) EffectiveType() StorageType
EffectiveType 实际生效的存储类型(远端构造失败降级 local 时如实返回 local)。
func (*StorageService) FileExists ¶
func (s *StorageService) FileExists(ctx context.Context, filePath string) bool
FileExists 检查文件是否存在
func (*StorageService) GetFileReader ¶
func (s *StorageService) GetFileReader(ctx context.Context, filePath string) (io.ReadCloser, int64, error)
GetFileReader 获取文件读取器(用于流式下载)
func (*StorageService) GetFileReaderRange ¶
func (s *StorageService) GetFileReaderRange(ctx context.Context, filePath string, start, length int64) (io.ReadCloser, int64, error)
GetFileReaderRange 区间读取文件(Range 下载/断点续传)。 返回 (区间读器, 对象总大小)。当前后端不支持区间读时返回 opendal.ErrRangeUnsupported,调用方应回退全量流式(200)。 start 越界(>= 文件大小)返回 os.ErrNotExist 语义错误(调用方 416)。
func (*StorageService) GetFileSize ¶
GetFileSize 获取文件大小
func (*StorageService) GetFileURL ¶
GetFileURL 获取文件URL
func (*StorageService) HeadObject ¶
HeadObject 返回对象大小与 ETag(s3 直传 Complete 时的存在性/大小核实)。
func (*StorageService) InitError ¶
func (s *StorageService) InitError() error
InitError 返回构造降级原因(无降级时为 nil)。
func (*StorageService) ListRemoteObjects ¶
func (s *StorageService) ListRemoteObjects(ctx context.Context, prefix string) ([]RemoteObjectInfo, error)
ListRemoteObjects 列举远端后端 prefix 下对象(递归)。 仅远端后端支持;本地后端返回错误(本地对账走 ReconcileOrphans 磁盘遍历)。
func (*StorageService) LocalAbsPath ¶
func (s *StorageService) LocalAbsPath(rel string) string
LocalAbsPath 本地后端下解析存储相对路径为绝对路径(仅 local 后端;远端返回空)。 供下载链路走 c.File(原生 Range/断点续传/MIME 推断);路径不存在返回空。
func (*StorageService) MergeChunks ¶
func (s *StorageService) MergeChunks(ctx context.Context, uploadID string, totalChunks int, savePath string) error
MergeChunks 合并分片。 local:顺序拼接落盘;远端:懒打开分片的链式读器 + 按总大小流式上传, 不整文件进内存。
func (*StorageService) PresignGetURL ¶
func (s *StorageService) PresignGetURL(ctx context.Context, objectKey string, expire time.Duration) (string, error)
PresignGetURL 生成真预签名直下 GET URL(短时效,下载 302 用)。
func (*StorageService) PresignPutURL ¶
func (s *StorageService) PresignPutURL(ctx context.Context, objectKey string, expire time.Duration) (string, error)
PresignPutURL 生成真预签名直传 PUT URL(客户端直传对象存储,服务器不过流量)。 仅 s3 等支持离线签名的后端可用;local/webdav 返回 ErrPresignUnsupported, 调用方(presign 域)据此回退自家中转。
func (*StorageService) Reload ¶
func (s *StorageService) Reload(config *StorageConfig) error
Reload 热切换存储后端(管理端切换存储时调用)。构造失败时保留原后端并返回错误。
func (*StorageService) SaveBytes ¶
SaveBytes 写入内存数据到相对路径(presign 直传使用)。 路径防御收敛在此处:相对 DataPath 计算清洗后的偏移,逃逸(../)即拒绝。
func (*StorageService) SaveChunk ¶
func (s *StorageService) SaveChunk(ctx context.Context, uploadID string, chunkIndex int, data []byte) error
SaveChunk 保存分片
func (*StorageService) SaveFile ¶
func (s *StorageService) SaveFile(ctx context.Context, file *multipart.FileHeader, savePath string) (*FileOperationResult, error)
SaveFile 保存文件。 落盘的同时用 io.TeeReader 流式计算 SHA-256(不额外占用整文件内存), 哈希写入 result.FileHash——这是秒传(按哈希秒传)与完整性的地基。
type StorageType ¶
type StorageType string
StorageType 存储类型
const ( StorageTypeLocal StorageType = "local" StorageTypeS3 StorageType = "s3" StorageTypeWebDAV StorageType = "webdav" StorageTypeFTP StorageType = "ftp" StorageTypeSFTP StorageType = "sftp" StorageTypeGCS StorageType = "gcs" StorageTypeAzBlob StorageType = "azureblob" StorageTypeHDFS StorageType = "hdfs" StorageTypeOneDrv StorageType = "onedrive" )
type StoredFileEntry ¶
type StoredFileEntry struct {
// RelPath 存储相对路径(含唯一文件名;local 下与合并写入路径一致)
RelPath string
// FileName 原始文件名(消毒后,仅展示)
FileName string
// Size 实际大小(handler 已复核)
Size int64
// FileHash SHA-256(可空:哈希失败不阻断分享)
FileHash string
}
StoredFileEntry 已落存储的文件项(多文件分享/访客投递等跨域流转的统一载体)。 语义约定:传输层保证物理文件已就位(直传保存/分片合并/presign 核实), 业务层只做装配。定义在本包使 request 等域引用它时无需依赖具体业务域。