fix: resolve meeting note files from oss urls
This commit is contained in:
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+60
-6
@@ -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 {
|
||||||
return meta
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ = 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)
|
||||||
|
|||||||
Reference in New Issue
Block a user