mirror of
https://github.com/siyuan-note/siyuan.git
synced 2026-03-06 12:50:16 +01:00
Signed-off-by: Daniel <845765@qq.com>
This commit is contained in:
parent
0e3a56826d
commit
3b1f0f3edb
1 changed files with 34 additions and 86 deletions
|
|
@ -17,12 +17,14 @@
|
||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"mime"
|
"mime"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
@ -246,103 +248,49 @@ func FilterUploadFileName(name string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TruncateLenFileName(name string) (ret string) {
|
func TruncateLenFileName(name string) (ret string) {
|
||||||
// 插入资源文件时文件名长度最大限制 189 字节
|
// 插入资源文件时文件名长度最大限制 189 字节 https://github.com/siyuan-note/siyuan/issues/7099
|
||||||
const maxTotal = 189
|
|
||||||
|
|
||||||
ext := filepath.Ext(name)
|
ext := filepath.Ext(name)
|
||||||
base := name[:len(name)-len(ext)]
|
extLen := len(ext)
|
||||||
|
var byteCount int
|
||||||
|
truncated := false
|
||||||
|
buf := bytes.Buffer{}
|
||||||
|
maxLen := 189 - extLen
|
||||||
|
var pdfAnnoPngPart string
|
||||||
|
if ".png" == ext {
|
||||||
|
// PNG 图片可能是 PDF 标注的截图,包含页面和旋转角度(name--P1--270-id.png),所以允许的长度更短一些
|
||||||
|
// https://github.com/siyuan-note/siyuan/pull/16714#issuecomment-3737987302
|
||||||
|
|
||||||
id := ast.NewNodeID()
|
pdfAnnoPngPattern := "-{0,1}P{0,1}[0-9]{0,4}-{0,1}[0-9]{1,3}-[0-9]{14}-[0-9a-zA-Z]{7}\\.png$"
|
||||||
// 预留 "-" + id + "-" 的字节数
|
regx := regexp.MustCompile(pdfAnnoPngPattern)
|
||||||
reservedForID := len(id) + 2
|
pdfAnnoPngPart = regx.FindString(name)
|
||||||
|
if "" != pdfAnnoPngPart {
|
||||||
available := maxTotal - len(ext) - reservedForID
|
maxLen -= len(pdfAnnoPngPart) + len(".png")
|
||||||
if available <= 0 {
|
name = strings.TrimSuffix(name, pdfAnnoPngPart)
|
||||||
// 空间不足以保留 base,退回到 "-id-" + ext(若仍超限则只返回扩展名)
|
|
||||||
candidate := "-" + id + "-" + ext
|
|
||||||
if len(candidate) <= maxTotal {
|
|
||||||
return candidate
|
|
||||||
}
|
}
|
||||||
if len(ext) <= maxTotal {
|
|
||||||
return ext
|
|
||||||
}
|
|
||||||
return ext
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 若 base 整体在可用字节内,直接返回原名
|
// 深入理解计算机系统原书第3版彩色扫描 -- 美兰德尔 E_布莱恩特Randal,E_·Bryant,等 龚奕利,贺莲 -- 计算机科学丛书, 3rd, 2016 -- 机械工业出版社123-P57-90-20260113113402-prc0u4k.png
|
||||||
if len(base) <= available {
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
||||||
runes := []rune(base)
|
for _, r := range name {
|
||||||
n := len(runes)
|
byteCount += utf8.RuneLen(r)
|
||||||
if n == 0 {
|
if maxLen < byteCount {
|
||||||
candidate := "-" + id + "-" + ext
|
truncated = true
|
||||||
if len(candidate) <= maxTotal {
|
break
|
||||||
return candidate
|
|
||||||
}
|
}
|
||||||
if len(ext) <= maxTotal {
|
buf.WriteRune(r)
|
||||||
return ext
|
|
||||||
}
|
|
||||||
return ext
|
|
||||||
}
|
}
|
||||||
|
if truncated {
|
||||||
// 计算每个 rune 的字节长度
|
if "" != pdfAnnoPngPart {
|
||||||
runeBytes := make([]int, n)
|
buf.WriteString(pdfAnnoPngPart)
|
||||||
for i, r := range runes {
|
|
||||||
runeBytes[i] = utf8.RuneLen(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从后往前尝试最多保留 3 个 rune,找到最大的 tailSize 使得 tailBytes <= available
|
|
||||||
tailSize := 0
|
|
||||||
tailBytes := 0
|
|
||||||
for t := 1; t <= 3 && t <= n; t++ {
|
|
||||||
b := 0
|
|
||||||
for i := n - t; i < n; i++ {
|
|
||||||
b += runeBytes[i]
|
|
||||||
}
|
|
||||||
if b <= available {
|
|
||||||
tailSize = t
|
|
||||||
tailBytes = b
|
|
||||||
} else {
|
} else {
|
||||||
break
|
buf.WriteString(ext)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if "" != pdfAnnoPngPart {
|
||||||
|
buf.WriteString(pdfAnnoPngPart)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ret = buf.String()
|
||||||
if tailSize == 0 {
|
|
||||||
// 连一个尾部 rune 都放不下,回退到 "-id-" 或扩展名
|
|
||||||
candidate := "-" + id + "-" + ext
|
|
||||||
if len(candidate) <= maxTotal {
|
|
||||||
return candidate
|
|
||||||
}
|
|
||||||
if len(ext) <= maxTotal {
|
|
||||||
return ext
|
|
||||||
}
|
|
||||||
return ext
|
|
||||||
}
|
|
||||||
|
|
||||||
// 可用于前缀的字节
|
|
||||||
availFront := available - tailBytes
|
|
||||||
// 前缀最多不能覆盖到尾部
|
|
||||||
maxFrontCount := n - tailSize
|
|
||||||
|
|
||||||
var frontRunes []rune
|
|
||||||
frontBytes := 0
|
|
||||||
for i := 0; i < maxFrontCount; i++ {
|
|
||||||
if frontBytes+runeBytes[i] > availFront {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
frontBytes += runeBytes[i]
|
|
||||||
frontRunes = append(frontRunes, runes[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
// 若前缀与尾部合并能覆盖全部 runes,则说明无需截断(理论上前面已判断过,但再验证一次)
|
|
||||||
if len(frontRunes) == maxFrontCount {
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
||||||
tailRunes := runes[n-tailSize:]
|
|
||||||
ret = string(frontRunes) + string(tailRunes) + "-" + id + "-" + ext
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue