Documentation
¶
Overview ¶
Package presign 实现预签名上传 service。
流程:
- 客户端调 Init 申请预签名 URL + token
- 客户端 PUT 直传文件到 URL
- 客户端调 Complete 通知服务写 share 表
- 服务返回 share_code
当前实现:fallback 走"自家直传 URL + token"模式(不依赖真实 S3/OSS 预签名)。 当 OpenDAL binding 接入后,可直接生成真实预签名 URL。
Index ¶
- Constants
- Variables
- type CompleteResult
- type InitMeta
- type InitResult
- type ObjectStore
- type PickupBinder
- type QuickShareMeta
- type QuickUploadResult
- type Service
- func (s *Service) Abort(ctx context.Context, uploadID, token string) error
- func (s *Service) CheckQuickUpload(ctx context.Context, userID uint, meta QuickShareMeta) (*QuickUploadResult, error)
- func (s *Service) Complete(ctx context.Context, uploadID, token, ownerIP string) (*CompleteResult, error)
- func (s *Service) GetMeta(ctx context.Context, uploadID string) (*InitMeta, error)
- func (s *Service) Init(ctx context.Context, meta InitMeta) (*InitResult, error)
- func (s *Service) SetObjectStore(o ObjectStore)
- func (s *Service) SetPickupBinder(b PickupBinder)
- func (s *Service) SetShareService(svc ShareServiceInterface)
- func (s *Service) SetStorage(st StorageWriter)
- func (s *Service) UploadDirect(ctx context.Context, uploadID, token string, body io.Reader, ...) error
- type ShareCreateReq
- type ShareCreateResp
- type ShareServiceInterface
- type StorageWriter
Constants ¶
const ( // SchemeSelf 自家中转:客户端 PUT /api/v1/presign/upload-direct/:uploadID SchemeSelf = "self" // SchemeS3 真·预签名直传:客户端 PUT 对象存储,服务器只签名不过流量 SchemeS3 = "s3" )
直传模式标记(meta.Scheme / InitResult.Scheme,服务端判定为准)
Variables ¶
var ( ErrUploadNotFound = errors.New("upload not found") ErrTokenInvalid = errors.New("upload token invalid") ErrUploadExpired = errors.New("upload expired") ErrAlreadyComplete = errors.New("upload already completed") )
错误定义
Functions ¶
This section is empty.
Types ¶
type CompleteResult ¶
type CompleteResult struct {
*InitMeta
OwnerIP string
PickupCode string // 6 位取件码(share 域铸造;永久分享/未注入 minter 为空)
}
CompleteResult Complete 返回结果(包含 share_code)
type InitMeta ¶
type InitMeta struct {
UploadID string `json:"upload_id"`
ObjectKey string `json:"object_key"`
FileName string `json:"file_name"`
FileSize int64 `json:"file_size"`
ContentType string `json:"content_type"`
Scheme string `json:"scheme"`
ExpireAt time.Time `json:"expire_at"`
Complete bool `json:"complete"`
UserID uint `json:"user_id"`
ExpireValue int32 `json:"expire_value"`
ExpireStyle string `json:"expire_style"`
RequireAuth bool `json:"require_auth"`
// PasswordHash 为 require_auth=true 时分享密码的 bcrypt 哈希(明文不落存储)
PasswordHash string `json:"password_hash,omitempty"`
// FileHash 直传完成后服务端计算的 SHA-256(写入 file_codes.file_hash,秒传依据)
// SessionTTL 直传会话/签名时效(handler 按管理配置下发;0=服务端默认 1h)
SessionTTL time.Duration `json:"-"`
FileHash string `json:"file_hash,omitempty"`
// PickupCode 匿名取件码直传绑定(2026-10-07):非空时 Complete 不新建分享,
// 而是把对象回填到该占位记录(/anonymous/generate 创建)。有效期/密码以
// 占位记录为准——本 meta 的 expire/auth 字段在绑定路径被忽略。
PickupCode string `json:"pickup_code,omitempty"`
// Note 文件备注(可空,随分享展示给取件人;2026-10-12 #489)
Note string `json:"note,omitempty"`
}
InitMeta init 元信息
type InitResult ¶
type InitResult struct {
UploadID string `json:"upload_id"`
UploadURL string `json:"upload_url"`
Method string `json:"method"`
Headers map[string]string `json:"headers"`
ExpireSeconds int32 `json:"expire_seconds"`
ObjectKey string `json:"object_key"`
Scheme string `json:"scheme"`
Token string `json:"token"`
}
InitResult init 返回
type ObjectStore ¶
type ObjectStore interface {
PresignPutURL(ctx context.Context, objectKey string, expire time.Duration) (string, error)
// HeadObject 直传完成核实用:对象必须真实存在并取实际大小(S3 为事实源)
HeadObject(ctx context.Context, objectKey string) (size int64, etag string, err error)
}
ObjectStore 真预签名直传能力(由 *storage.StorageService 实现)。 PresignPutURL 对 local/webdav 返回 storage.ErrPresignUnsupported,调用方回退自家中转。
type PickupBinder ¶ added in v0.14.5
type PickupBinder interface {
// ResolvePlaceholder 校验取件码是待回填占位分享,返回其 8 位分享码
ResolvePlaceholder(ctx context.Context, pickupCode string) (string, error)
// BindFilePath 把直传对象回填到占位分享(file_path+size;note 非空一并写入)
BindFilePath(ctx context.Context, shareCode, filePath string, size int64, note string) error
}
PickupBinder 匿名取件码占位绑定窄接口(app/anonymous.Service 结构性满足; presign 域不 import anonymous 域,由 bootstrap 注入)。
type QuickShareMeta ¶ added in v0.17.0
type QuickShareMeta struct {
}
QuickShareMeta 秒传建分享所需元数据(presign init 请求携带)。
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service 预签名上传 service
func NewService ¶
NewService 创建 service。rdb nil 归一化:typed-nil 接口会骗过 "Redis 可用"守卫(!= nil 判真)。 rdb 为 nil(redis.host 未配置)时进入单机内存模式:直传会话存进程内 TTL KV,预签名直传全功能可用(单进程语义等价;重启未完成会话作废)。
func (*Service) CheckQuickUpload ¶
func (s *Service) CheckQuickUpload(ctx context.Context, userID uint, meta QuickShareMeta) (*QuickUploadResult, error)
CheckQuickUpload 秒传检查(2026-10-12 重做,D1=A 同用户内去重): 命中**调用者自己**历史同 hash+size 文件时,新建一条分享(调用者元数据: 名称/过期/密码)引用既有存储对象,免直传直接出码。
此前语义=回借既有分享的 code(全库匹配)——两处不可接受:跨用户匹配是 存在性 oracle(撞库探测谁传过什么);借来的分享生命周期/密码/过期全归 原主,本次请求的元数据被静默丢弃。现改为同用户 + 建新分享。
func (*Service) Complete ¶
func (s *Service) Complete(ctx context.Context, uploadID, token, ownerIP string) (*CompleteResult, error)
Complete 完成通知(调 share service 写分享表)
func (*Service) SetObjectStore ¶
func (s *Service) SetObjectStore(o ObjectStore)
SetObjectStore 注入真预签名直传能力(s3 后端;不支持时 Init 自动回退自家中转)
func (*Service) SetPickupBinder ¶ added in v0.14.5
func (s *Service) SetPickupBinder(b PickupBinder)
SetPickupBinder 注入匿名取件码占位绑定(anonymous 域实现;nil = 绑定通道不可用)
func (*Service) SetShareService ¶
func (s *Service) SetShareService(svc ShareServiceInterface)
SetShareService 注入 share service(用于 Complete 时写分享表)
func (*Service) SetStorage ¶
func (s *Service) SetStorage(st StorageWriter)
SetStorage 注入存储服务(直传按当前激活后端落盘,含路径防御)
func (*Service) UploadDirect ¶
func (s *Service) UploadDirect(ctx context.Context, uploadID, token string, body io.Reader, declaredSize int64) error
UploadDirect 处理预签名直传:校验 token → 流式写文件(meta.ObjectKey 路径)。 由 bootstrap 注册的 PUT /api/v1/presign/upload-direct/:uploadID 端点调用。 body 流式消费(配合 hertz StreamRequestBody),大文件不再整体进内存; 写入字节数必须与 init 申报的 meta.FileSize 完全一致,超出即拒并清理。
type ShareCreateReq ¶ added in v0.15.2
type ShareCreateReq struct {
}
ShareCreateReq 经 share 域建分享的窄化请求(消费侧词汇表)。 此前本域直接 import share.ShareFileReq/ShareResp 构成唯一约定 app 跨域边 (presign→share),2026-10-10 消解:字段与 share.CreateShare 对齐, bootstrap 适配器(presignShareAdapter)转换到 share 域类型——与 requestShareGateway/mcpShareAdapter 同款装配点转换模式。
type ShareCreateResp ¶ added in v0.15.2
type ShareCreateResp struct {
}
ShareCreateResp share 域建分享结果的窄视图(presign 消费字段)。
type ShareServiceInterface ¶
type ShareServiceInterface interface {
}
ShareServiceInterface share service 接口(消费侧窄接口,bootstrap 注入 share 域适配器;避免 app 跨域 import)。