fix: resolve meeting note files from oss urls

This commit is contained in:
richjohnrambo
2026-09-18 16:29:14 +08:00
parent ef2967b056
commit 06e3f0b489
2 changed files with 84 additions and 6 deletions
+24
View File
@@ -50,3 +50,27 @@ func TestParseUploadFileIDAcceptsExtension(t *testing.T) {
t.Fatal("storageName is empty") t.Fatal("storageName is empty")
} }
} }
func TestParseUploadFileIDAcceptsOSSURL(t *testing.T) {
decodedID, storageName := parseUploadFileID("https://oss.example.com/files/lxzvtUzicEo.pdf?Expires=1")
if decodedID <= 0 {
t.Fatalf("decodedID=%d, want positive", decodedID)
}
if storageName == "" {
t.Fatal("storageName is empty")
}
}
func TestParseUploadFileIDAcceptsObjectKey(t *testing.T) {
decodedID, storageName := parseUploadFileID("tenants/1/2026/09/s4oo7nkm4jyeu")
if decodedID != 0 {
t.Fatalf("decodedID=%d, want 0 for object key", decodedID)
}
if storageName != "s4oo7nkm4jyeu" {
t.Fatalf("storageName=%q, want s4oo7nkm4jyeu", storageName)
}
candidates := uploadLocationCandidates("tenants/1/2026/09/s4oo7nkm4jyeu", storageName)
if len(candidates) < 2 || candidates[0] != "s4oo7nkm4jyeu" || candidates[1] != "tenants/1/2026/09/s4oo7nkm4jyeu" {
t.Fatalf("candidates=%#v", candidates)
}
}
+59 -5
View File
@@ -10,6 +10,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"mime" "mime"
"net/url"
"path/filepath" "path/filepath"
"strings" "strings"
"sync" "sync"
@@ -690,7 +691,8 @@ type fileUploadMetadata struct {
func (s *Store) fileUploadMetadata(ctx context.Context, fileID string) fileUploadMetadata { func (s *Store) fileUploadMetadata(ctx context.Context, fileID string) fileUploadMetadata {
var meta fileUploadMetadata var meta fileUploadMetadata
decodedID, storageName := parseUploadFileID(fileID) decodedID, storageName := parseUploadFileID(fileID)
if decodedID <= 0 && storageName == "" { locationCandidates := uploadLocationCandidates(fileID, storageName)
if decodedID <= 0 && len(locationCandidates) == 0 {
return meta return meta
} }
if decodedID > 0 { if decodedID > 0 {
@@ -699,16 +701,18 @@ func (s *Store) fileUploadMetadata(ctx context.Context, fileID string) fileUploa
return meta return meta
} }
} }
if storageName == "" { for _, candidate := range locationCandidates {
err := s.db.GetContext(ctx, &meta, `SELECT IFNULL(mimetype,'') AS mimetype,IFNULL(size,0) AS size,IFNULL(etag,'') AS etag,IFNULL(location,'') AS location
FROM im_fileuploads WHERE location=? OR location LIKE ? ORDER BY createdat DESC LIMIT 1`, candidate, "%/"+candidate)
if err == nil {
return meta return meta
} }
_ = s.db.GetContext(ctx, &meta, `SELECT IFNULL(mimetype,'') AS mimetype,IFNULL(size,0) AS size,IFNULL(etag,'') AS etag,IFNULL(location,'') AS location }
FROM im_fileuploads WHERE location=? OR location LIKE ? ORDER BY createdat DESC LIMIT 1`, storageName, "%/"+storageName)
return meta return meta
} }
func parseUploadFileID(fileID string) (int64, string) { func parseUploadFileID(fileID string) (int64, string) {
name := strings.TrimSpace(fileID) name := uploadFileName(fileID)
if dot := strings.LastIndexByte(name, '.'); dot > 0 { if dot := strings.LastIndexByte(name, '.'); dot > 0 {
ext := name[dot+1:] ext := name[dot+1:]
if len(ext) == 0 || len(ext) > 16 { if len(ext) == 0 || len(ext) > 16 {
@@ -723,6 +727,9 @@ func parseUploadFileID(fileID string) (int64, string) {
} }
decoded, err := base64.URLEncoding.WithPadding(base64.NoPadding).DecodeString(name) decoded, err := base64.URLEncoding.WithPadding(base64.NoPadding).DecodeString(name)
if err != nil || len(decoded) < 8 { if err != nil || len(decoded) < 8 {
if isStorageFileName(name) {
return 0, name
}
return 0, "" return 0, ""
} }
storageData := make([]byte, 8) storageData := make([]byte, 8)
@@ -737,6 +744,53 @@ func parseUploadFileID(fileID string) (int64, string) {
return int64(binary.LittleEndian.Uint64(plain)), storageName return int64(binary.LittleEndian.Uint64(plain)), storageName
} }
func uploadFileName(fileID string) string {
name := strings.TrimSpace(fileID)
if parsed, err := url.Parse(name); err == nil && parsed.Path != "" {
name = parsed.Path
}
if q := strings.IndexAny(name, "?#"); q >= 0 {
name = name[:q]
}
name = strings.TrimRight(strings.ReplaceAll(name, "\\", "/"), "/")
if slash := strings.LastIndexByte(name, '/'); slash >= 0 {
name = name[slash+1:]
}
return strings.TrimSpace(name)
}
func uploadLocationCandidates(fileID, storageName string) []string {
seen := map[string]bool{}
var candidates []string
add := func(value string) {
value = strings.Trim(strings.TrimSpace(value), "/")
if value == "" || seen[value] {
return
}
seen[value] = true
candidates = append(candidates, value)
}
add(storageName)
raw := strings.TrimSpace(fileID)
if parsed, err := url.Parse(raw); err == nil && parsed.Path != "" {
add(parsed.Path)
}
add(raw)
return candidates
}
func isStorageFileName(name string) bool {
if len(name) != 13 {
return false
}
for _, r := range name {
if (r < 'a' || r > 'z') && (r < '2' || r > '7') {
return false
}
}
return true
}
func normalizeMeetingNoteFileMetadata(input MeetingNoteFileInput, meta fileUploadMetadata, fileID string) (string, string, int64, string) { func normalizeMeetingNoteFileMetadata(input MeetingNoteFileInput, meta fileUploadMetadata, fileID string) (string, string, int64, string) {
mimeType := firstNonEmpty(input.MIMEType, meta.MIMEType) mimeType := firstNonEmpty(input.MIMEType, meta.MIMEType)
fileSize := int64(0) fileSize := int64(0)