From 6192e87058c4233b7f7243b53f91bdcda9210817 Mon Sep 17 00:00:00 2001
From: Jeffrey Chen <78434827+TCOTC@users.noreply.github.com>
Date: Fri, 9 Jan 2026 11:27:58 +0800
Subject: [PATCH 1/3] :art: Force download exported files
https://github.com/siyuan-note/siyuan/pull/16774 (#16796)
---
kernel/server/serve.go | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/kernel/server/serve.go b/kernel/server/serve.go
index e55ee92d2..ed1f6c7e7 100644
--- a/kernel/server/serve.go
+++ b/kernel/server/serve.go
@@ -265,7 +265,39 @@ func rewritePortJSON(pid, port string) {
func serveExport(ginServer *gin.Engine) {
// Potential data export disclosure security vulnerability https://github.com/siyuan-note/siyuan/issues/12213
exportGroup := ginServer.Group("/export/", model.CheckAuth)
- exportGroup.Static("/", filepath.Join(util.TempDir, "export"))
+ exportBaseDir := filepath.Join(util.TempDir, "export")
+
+ // 应下载而不是查看导出的文件
+ exportGroup.GET("/*filepath", func(c *gin.Context) {
+ filePath := strings.TrimPrefix(c.Request.URL.Path, "/export/")
+
+ decodedPath, err := url.PathUnescape(filePath)
+ if err != nil {
+ decodedPath = filePath
+ }
+
+ fullPath := filepath.Join(exportBaseDir, decodedPath)
+
+ fileInfo, err := os.Stat(fullPath)
+ if os.IsNotExist(err) {
+ c.Status(http.StatusNotFound)
+ return
+ }
+ if err != nil {
+ c.Status(http.StatusInternalServerError)
+ return
+ }
+
+ if fileInfo.IsDir() {
+ c.Status(http.StatusNotFound)
+ return
+ }
+
+ fileName := filepath.Base(decodedPath)
+ c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", fileName))
+
+ c.File(fullPath)
+ })
}
func serveWidgets(ginServer *gin.Engine) {
From 2162a43a61a98c014a8a08bd828bb670b2b32202 Mon Sep 17 00:00:00 2001
From: Daniel <845765@qq.com>
Date: Fri, 9 Jan 2026 11:30:04 +0800
Subject: [PATCH 2/3] :art: Display a confirmation prompt when inserting large
assets 256MB https://github.com/siyuan-note/siyuan/issues/16685
Signed-off-by: Daniel <845765@qq.com>
---
app/pnpm-lock.yaml | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/app/pnpm-lock.yaml b/app/pnpm-lock.yaml
index 1191b5269..8eb0b583b 100644
--- a/app/pnpm-lock.yaml
+++ b/app/pnpm-lock.yaml
@@ -11,9 +11,6 @@ importers:
'@electron/remote':
specifier: ^2.1.3
version: 2.1.3(electron@39.2.7)
- pretty-bytes:
- specifier: ^7.1.0
- version: 7.1.0
devDependencies:
'@eslint/eslintrc':
specifier: ^3.3.1
@@ -60,6 +57,9 @@ importers:
file-loader:
specifier: ^6.2.0
version: 6.2.0(webpack@5.101.3)
+ filesize:
+ specifier: ^11.0.13
+ version: 11.0.13
globals:
specifier: ^15.12.0
version: 15.15.0
@@ -1395,6 +1395,10 @@ packages:
filelist@1.0.4:
resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==}
+ filesize@11.0.13:
+ resolution: {integrity: sha512-mYJ/qXKvREuO0uH8LTQJ6v7GsUvVOguqxg2VTwQUkyTPXXRRWPdjuUPVqdBrJQhvci48OHlNGRnux+Slr2Rnvw==}
+ engines: {node: '>= 10.8.0'}
+
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
@@ -2228,10 +2232,6 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
- pretty-bytes@7.1.0:
- resolution: {integrity: sha512-nODzvTiYVRGRqAOvE84Vk5JDPyyxsVk0/fbA/bq7RqlnhksGpset09XTxbpvLTIjoaF7K8Z8DG8yHtKGTPSYRw==}
- engines: {node: '>=20'}
-
pretty-error@4.0.0:
resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==}
@@ -4263,6 +4263,8 @@ snapshots:
dependencies:
minimatch: 5.1.6
+ filesize@11.0.13: {}
+
fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
@@ -5108,8 +5110,6 @@ snapshots:
prelude-ls@1.2.1: {}
- pretty-bytes@7.1.0: {}
-
pretty-error@4.0.0:
dependencies:
lodash: 4.17.21
From 8801b7e93367817acbd50fc5abbbcc56292aa1a3 Mon Sep 17 00:00:00 2001
From: Daniel <845765@qq.com>
Date: Fri, 9 Jan 2026 11:40:06 +0800
Subject: [PATCH 3/3] :art: Display a confirmation prompt when inserting large
assets 256MB https://github.com/siyuan-note/siyuan/issues/16685
Signed-off-by: Daniel <845765@qq.com>
---
app/src/asset/anno.ts | 2 +-
app/src/protyle/render/av/asset.ts | 2 +-
app/src/protyle/upload/index.ts | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/app/src/asset/anno.ts b/app/src/asset/anno.ts
index aec90b224..a91098ded 100644
--- a/app/src/asset/anno.ts
+++ b/app/src/asset/anno.ts
@@ -743,7 +743,7 @@ const copyAnno = (idPath: string, fileName: string, pdf: any) => {
const imageName = content + ".png";
let msg = "";
if (Constants.SIZE_UPLOAD_TIP_SIZE <= blob.size) {
- msg = window.siyuan.languages.uploadFileTooLarge.replace("${x}", imageName).replace("${y}", filesize(blob.size, {standard: "jedec"}));
+ msg = window.siyuan.languages.uploadFileTooLarge.replace("${x}", imageName).replace("${y}", filesize(blob.size, {standard: "iec"}));
}
confirmDialog(msg ? window.siyuan.languages.upload : "", msg, () => {
const formData = new FormData();
diff --git a/app/src/protyle/render/av/asset.ts b/app/src/protyle/render/av/asset.ts
index 7a2af2f19..3a8169f0b 100644
--- a/app/src/protyle/render/av/asset.ts
+++ b/app/src/protyle/render/av/asset.ts
@@ -427,7 +427,7 @@ export const dragUpload = (files: ILocalFiles[], protyle: IProtyle, cellElement:
const assetPaths: string[] = [];
files.forEach(item => {
if (item.size && Constants.SIZE_UPLOAD_TIP_SIZE <= item.size) {
- msg += window.siyuan.languages.uploadFileTooLarge.replace("${x}", item.path).replace("${y}", filesize(item.size, {standard: "jedec"})) + "
";
+ msg += window.siyuan.languages.uploadFileTooLarge.replace("${x}", item.path).replace("${y}", filesize(item.size, {standard: "iec"})) + "
";
}
assetPaths.push(item.path);
});
diff --git a/app/src/protyle/upload/index.ts b/app/src/protyle/upload/index.ts
index 0947dae47..3a736c1ed 100644
--- a/app/src/protyle/upload/index.ts
+++ b/app/src/protyle/upload/index.ts
@@ -220,7 +220,7 @@ export const uploadLocalFiles = (files: ILocalFiles[], protyle: IProtyle, isUplo
const assetPaths: string[] = [];
files.forEach(item => {
if (item.size && Constants.SIZE_UPLOAD_TIP_SIZE <= item.size) {
- msg += window.siyuan.languages.uploadFileTooLarge.replace("${x}", item.path).replace("${y}", filesize(item.size, {standard: "jedec"})) + "
";
+ msg += window.siyuan.languages.uploadFileTooLarge.replace("${x}", item.path).replace("${y}", filesize(item.size, {standard: "iec"})) + "
";
}
assetPaths.push(item.path);
});
@@ -311,7 +311,7 @@ export const uploadFiles = (protyle: IProtyle, files: FileList | DataTransferIte
for (let i = 0, iMax = validateResult.files.length; i < iMax; i++) {
formData.append(protyle.options.upload.fieldName, validateResult.files[i]);
if (Constants.SIZE_UPLOAD_TIP_SIZE <= validateResult.files[i].size) {
- msg += window.siyuan.languages.uploadFileTooLarge.replace("${x}", validateResult.files[i].name).replace("${y}", filesize(validateResult.files[i].size, {standard: "jedec"})) + "
";
+ msg += window.siyuan.languages.uploadFileTooLarge.replace("${x}", validateResult.files[i].name).replace("${y}", filesize(validateResult.files[i].size, {standard: "iec"})) + "
";
}
}