Documentation
¶
Overview ¶
Package anonymous 实现匿名取件 service(仿 vastsa/PigeonBox UX)。
核心流程:
- 上传方:上传文件后,调用 GenerateCode 获取 6 位取件码(建立 pickup_code → share_code 映射)
- 取件方:输入 6 位码 + 可选密码,按码取文件
- 系统:校验(DB 为准)→ 扣减次数(DB 原子)→ 返回下载信息
设计要点(DB 为唯一真相源):
- Redis 仅存 pickup_code → share_code 映射 + 展示信息(文件名等)
- 过期时间、剩余次数、密码哈希全部以 file_codes 表为准
- 取件码字符表去掉易混淆字符 0/O/1/I/L
Index ¶
- Variables
- type AnonymousShareParams
- type BlockedError
- type CodeMeta
- type Service
- func (s *Service) BindFilePath(ctx context.Context, shareCode, filePath string, size int64) error
- func (s *Service) Cancel(ctx context.Context, code string) error
- func (s *Service) CreateAnonymousShare(ctx context.Context, p AnonymousShareParams) (string, error)
- func (s *Service) GenerateCode(ctx context.Context, meta CodeMeta, expireAt time.Time) (string, error)
- func (s *Service) MintForShare(ctx context.Context, shareCode, fileName string, fileSize int64, ...) (string, error)
- func (s *Service) Peek(ctx context.Context, code string) (*CodeMeta, *model.FileCode, error)
- func (s *Service) ResolvePlaceholder(ctx context.Context, pickupCode string) (string, error)
- func (s *Service) Retrieve(ctx context.Context, code, password string) (*CodeMeta, error)
Constants ¶
This section is empty.
Variables ¶
var ( ErrCodeNotFound = errors.New("pickup code not found") ErrCodeExpired = errors.New("pickup code expired") ErrCodeExhausted = errors.New("pickup code exhausted") ErrPasswordWrong = errors.New("password wrong") ErrNotReady = errors.New("share upload incomplete") // 登记占位未回填物理文件 )
错误哨兵
Functions ¶
This section is empty.
Types ¶
type BlockedError ¶
type BlockedError struct{ Status string }
BlockedError 分享处于管控拒绝态(治理状态机)。 handler 侧 errors.As 后按 ErrCode 透传(20012 blocked / 20013 pending_review)。
func (*BlockedError) ErrCode ¶
func (e *BlockedError) ErrCode() int
func (*BlockedError) Error ¶
func (e *BlockedError) Error() string
type CodeMeta ¶
type CodeMeta struct {
FileName string
FileSize int64
ContentType string
RequireAuth bool // 仅展示"是否需要密码"
}
CodeMeta 取件码展示信息(仅存于 Redis,真实状态查 DB)
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service 匿名取件 service。 Redis 仅存映射 + 展示信息;过期/次数/密码等真实状态全部以 file_codes 表为准。
func NewService ¶
func NewService(rdb *redis.Client, fileCodeRepo *dao.FileCodeRepository) *Service
NewService 创建 service。fileCodeRepo 为 nil 时内部自建(Retrieve 需查 DB)。 rdb nil 归一化:typed-nil 接口会骗过"Redis 可用"守卫(!= nil 判真)。 rdb 为 nil(redis.host 未配置)时进入单机内存模式:映射/展示信息存进程内 TTL KV,匿名取件全功能可用(单进程语义等价;重启丢失、不跨副本共享)。
func (*Service) BindFilePath ¶ added in v0.14.5
BindFilePath 把直传完成的对象回填到占位分享(匿名取件码直传通道的最后一公里)。 以实际落盘对象为准更新 file_path 与 size;完成标记由调用方(presign Complete)保证。 占位记录自带 UUIDFileName(generate 的展示名),不清掉会被 GetFilePath() 拼成 objectKey/文件名 的双重路径——直传对象 key 本身就是完整相对路径。
func (*Service) CreateAnonymousShare ¶
CreateAnonymousShare 端到端:建 file_codes 记录 + 生成取件码。 供 gen handler 调用,避免 handler 直接操作 DAO;密码在此 bcrypt 哈希后存 DB。 返回 6 位取件码。
func (*Service) GenerateCode ¶
func (s *Service) GenerateCode(ctx context.Context, meta CodeMeta, expireAt time.Time) (string, error)
GenerateCode 生成 6 位取件码,建立 pickup_code → share_code 映射。 expireAt 决定 Redis key 的 TTL(应与 DB 记录过期时间对齐)。
func (*Service) MintForShare ¶ added in v0.14.5
func (s *Service) MintForShare(ctx context.Context, shareCode, fileName string, fileSize int64, requireAuth bool, expireAt *time.Time) (string, error)
MintForShare 为既有文件分享铸造 6 位取件码(仅写 KV 映射,不动 DB 记录)。 供 app/share 经窄接口在 CreateShare 成功后调用——直传/直传分片/秒传各通道 的文件分享统一获得取件码(对齐上游"文件另有 N 位取件码"语义)。
- expireAt nil(永久分享)→ 返回空串不铸造:映射 TTL 无法对齐永久语义, 永久分享继续用 8 位分享码(lookupShareCode 的 DB 回退路径天然支持)。
- KV 写失败返回错误但调用方应视为非致命(出码主流程不阻断)。
func (*Service) ResolvePlaceholder ¶ added in v0.14.5
ResolvePlaceholder 校验取件码对应一个"待回填"的占位分享(/anonymous/generate 创建、FilePath 为空),返回其 8 位分享码。供 presign 直传绑定通道在 Init 时 预检、Complete 时定位回填目标。 非占位(已完成上传)/不存在/已过期 → 显式错误,防把对象绑到任意分享上。