- 全项目版本号统一:v3.x 迭代号(26.9/26.9/26.9/26.9 及裸 v2/v3)→ 26.9, 覆盖 Go 注释 / 文档 / openapi.yaml / README×4 / 前端源码(80+ 处) - v31_test.go 更名 custom_code_test.go;TestV2AccessorDefaults → TestKVAccessorDefaults - docs/api/00-overview.md 更新日志合并为单条 26.9 条目(修复错位拼接) - .goreleaser.yaml 头部注释与实际一致(Pro 2.18.1 / GITEA_TOKEN / semver tag 要求) - CI:release-image.yml → ci.yml,仅保留 vet+test 门禁; 镜像发布移交 GoReleaser Pro(原 build-push 的 tag 校验与 26.9 版本方案冲突,历史 9 次失败) - 前端重建:server/web/dist 与 web-embed 同步(docs 文案嵌入更新)
This commit is contained in:
@@ -51,7 +51,7 @@ type presignInitRequest struct {
|
||||
FileSize int64 `json:"file_size" form:"file_size"`
|
||||
ExpireValue int `json:"expire_value" form:"expire_value"`
|
||||
ExpireStyle string `json:"expire_style" form:"expire_style"`
|
||||
Code string `json:"code" form:"code"` // v3.1:自定义提取码(init 时校验,完成时落库)
|
||||
Code string `json:"code" form:"code"` // 26.9:自定义提取码(init 时校验,完成时落库)
|
||||
}
|
||||
|
||||
// presignInit 初始化预签名上传(对齐参考 presign_upload_init):
|
||||
@@ -74,7 +74,7 @@ func (d *Deps) presignInit(c *gin.Context) {
|
||||
response.Fail(c, http.StatusBadRequest, "文件名非法")
|
||||
return
|
||||
}
|
||||
// v3.1:自定义提取码提前校验(init 时快速失败;完成请求须再次携带)
|
||||
// 26.9:自定义提取码提前校验(init 时快速失败;完成请求须再次携带)
|
||||
if err := validatePickupCode(req.Code); err != nil {
|
||||
auditRecordFailed(c, d.AuditSvc, "提取码非法")
|
||||
respondError(c, err)
|
||||
@@ -86,7 +86,7 @@ func (d *Deps) presignInit(c *gin.Context) {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
// v2 需求 ④⑩:动态策略校验(max_file_size,0=回落 uploadSize)
|
||||
// 26.9 需求 ④⑩:动态策略校验(max_file_size,0=回落 uploadSize)
|
||||
if err := d.CurrentUploadPolicy().CheckSize(req.FileSize); err != nil {
|
||||
auditUploadEntry(c, "", safeName, req.FileSize, 0)
|
||||
auditRecordFailed(c, d.AuditSvc, "文件大小超过限制")
|
||||
@@ -146,7 +146,7 @@ func (d *Deps) presignInit(c *gin.Context) {
|
||||
FileSize: req.FileSize,
|
||||
SavePath: savePath,
|
||||
Mode: mode,
|
||||
Engine: d.Store.CurrentName(), // v3:会话归属引擎
|
||||
Engine: d.Store.CurrentName(), // 26.9:会话归属引擎
|
||||
ExpireValue: req.ExpireValue,
|
||||
ExpireStyle: req.ExpireStyle,
|
||||
ExpiresAt: time.Now().Add(presignSessionExpires * time.Second),
|
||||
@@ -195,7 +195,7 @@ func (d *Deps) presignProxy(c *gin.Context) {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
// v3.1:自定义提取码随代理上传表单携带(init 时已预校验)
|
||||
// 26.9:自定义提取码随代理上传表单携带(init 时已预校验)
|
||||
if err := validatePickupCode(c.PostForm("code")); err != nil {
|
||||
auditUploadEntry(c, uploadID, session.FileName, session.FileSize, 0)
|
||||
auditRecordFailed(c, d.AuditSvc, "提取码非法")
|
||||
@@ -234,7 +234,7 @@ func (d *Deps) presignProxy(c *gin.Context) {
|
||||
if err == nil {
|
||||
defer func() { _ = f.Close() }()
|
||||
if err = validateFileMagic(d.Cfg, session.FileName, fh.Header.Get("Content-Type"), readMultipartHeader(f, 64)); err == nil {
|
||||
// v3:落盘走会话归属引擎
|
||||
// 26.9:落盘走会话归属引擎
|
||||
var ps storage.Storage
|
||||
ps, sErr := d.storeFor(session.Engine)
|
||||
if sErr != nil {
|
||||
@@ -259,7 +259,7 @@ func (d *Deps) presignProxy(c *gin.Context) {
|
||||
releaseStorage(ctx, d.DB, "presign:"+uploadID)
|
||||
if err != nil {
|
||||
if ps, sErr := d.storeFor(session.Engine); sErr == nil {
|
||||
_ = ps.DeleteFile(ctx, session.SavePath) // v3:清理走归属引擎
|
||||
_ = ps.DeleteFile(ctx, session.SavePath) // 26.9:清理走归属引擎
|
||||
}
|
||||
auditUploadEntry(c, uploadID, session.FileName, session.FileSize, 0)
|
||||
auditRecordFailed(c, d.AuditSvc, "创建分享失败")
|
||||
@@ -299,7 +299,7 @@ func (d *Deps) presignConfirm(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// v3:直传文件存在性按会话归属引擎检查(直传可能落在旧引擎)
|
||||
// 26.9:直传文件存在性按会话归属引擎检查(直传可能落在旧引擎)
|
||||
psCheck, sErr := d.storeFor(session.Engine)
|
||||
if sErr != nil {
|
||||
auditUploadEntry(c, uploadID, session.FileName, session.FileSize, 0)
|
||||
@@ -307,7 +307,7 @@ func (d *Deps) presignConfirm(c *gin.Context) {
|
||||
respondError(c, mapStorageError(sErr))
|
||||
return
|
||||
}
|
||||
// v3.1:自定义提取码随确认请求携带(query 或 JSON/form body,均可选)
|
||||
// 26.9:自定义提取码随确认请求携带(query 或 JSON/form body,均可选)
|
||||
customCode := c.Query("code")
|
||||
if customCode == "" && c.Request.Body != nil && c.Request.ContentLength != 0 {
|
||||
var fin struct {
|
||||
@@ -378,7 +378,7 @@ func (d *Deps) presignConfirm(c *gin.Context) {
|
||||
releaseStorage(ctx, d.DB, "presign:"+uploadID)
|
||||
if err != nil {
|
||||
if ps, sErr := d.storeFor(session.Engine); sErr == nil {
|
||||
_ = ps.DeleteFile(ctx, session.SavePath) // v3:清理走归属引擎
|
||||
_ = ps.DeleteFile(ctx, session.SavePath) // 26.9:清理走归属引擎
|
||||
}
|
||||
auditUploadEntry(c, uploadID, session.FileName, session.FileSize, 0)
|
||||
auditRecordFailed(c, d.AuditSvc, "创建分享失败")
|
||||
@@ -399,7 +399,7 @@ func (d *Deps) createRecordFromSession(c *gin.Context, session *model.PresignUpl
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// v3.1:完成请求的自定义提取码兜底校验(init 已验,防只发完成请求绕过)
|
||||
// 26.9:完成请求的自定义提取码兜底校验(init 已验,防只发完成请求绕过)
|
||||
if err := validatePickupCode(customCode); err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -420,10 +420,10 @@ func (d *Deps) createRecordFromSession(c *gin.Context, session *model.PresignUpl
|
||||
ExpiredAt: exp.ExpiredAt,
|
||||
ExpiredCount: exp.ExpiredCount,
|
||||
UsedCount: exp.UsedCount,
|
||||
Engine: session.Engine, // v3:归属引擎戳
|
||||
Engine: session.Engine, // 26.9:归属引擎戳
|
||||
}
|
||||
if err := d.DB.WithContext(ctx).Create(&fc).Error; err != nil {
|
||||
return "", mapCodeConflict(err) // v3.1:并发占用自定义码 → 友好 400
|
||||
return "", mapCodeConflict(err) // 26.9:并发占用自定义码 → 友好 400
|
||||
}
|
||||
return code, nil
|
||||
}
|
||||
@@ -474,7 +474,7 @@ func (d *Deps) presignCancel(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if session.Mode == "direct" {
|
||||
// v3:清理走会话归属引擎
|
||||
// 26.9:清理走会话归属引擎
|
||||
if ps, sErr := d.storeFor(session.Engine); sErr == nil {
|
||||
if exists, eErr := ps.FileExists(ctx, session.SavePath); eErr == nil && exists {
|
||||
_ = ps.DeleteFile(ctx, session.SavePath)
|
||||
|
||||
Reference in New Issue
Block a user