🎨 Support importing markdown zip on the browser (#14950)

This commit is contained in:
zhangziqian 2025-06-02 21:14:04 +08:00 committed by GitHub
parent 88c7a66e68
commit 12cc17bd06
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 122 additions and 17 deletions

View file

@ -761,7 +761,8 @@ export const genImportMenu = (notebookId: string, pathString: string) => {
id: "import",
icon: "iconDownload",
label: window.siyuan.languages.import,
submenu: [{
submenu: [
{
id: "importSiYuanZip",
icon: "iconSiYuan",
label: 'SiYuan .sy.zip<input class="b3-form__upload" type="file" accept="application/zip">',
@ -779,6 +780,24 @@ export const genImportMenu = (notebookId: string, pathString: string) => {
});
}
},
{
id: "importMarkdownZip",
icon: "iconMarkdown",
label: 'Markdown .zip<input class="b3-form__upload" type="file" accept="application/zip">',
bind: (element) => {
element.querySelector(".b3-form__upload").addEventListener("change", (event: InputEvent & {
target: HTMLInputElement
}) => {
const formData = new FormData();
formData.append("file", event.target.files[0]);
formData.append("notebook", notebookId);
formData.append("toPath", pathString);
fetchPost("/api/import/importZipMd", formData, () => {
reloadDocTree();
});
});
}
},
/// #if !BROWSER
importstdmd("Markdown " + window.siyuan.languages.doc, true),
importstdmd("Markdown " + window.siyuan.languages.folder)

View file

@ -21,6 +21,7 @@ import (
"net/http"
"os"
"path/filepath"
"strings"
"github.com/88250/gulu"
"github.com/gin-gonic/gin"
@ -185,3 +186,87 @@ func importStdMd(c *gin.Context) {
return
}
}
func importZipMd(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(200, ret)
util.PushEndlessProgress(model.Conf.Language(73))
defer util.ClearPushProgress(100)
form, err := c.MultipartForm()
if err != nil {
logging.LogErrorf("parse import .zip failed: %s", err)
ret.Code = -1
ret.Msg = err.Error()
return
}
files := form.File["file"]
if 1 > len(files) {
logging.LogErrorf("parse import .zip failed, no file found")
ret.Code = -1
ret.Msg = "no file found"
return
}
file := files[0]
reader, err := file.Open()
if err != nil {
logging.LogErrorf("read import .zip failed: %s", err)
ret.Code = -1
ret.Msg = err.Error()
return
}
importDir := filepath.Join(util.TempDir, "import")
if err = os.MkdirAll(importDir, 0755); err != nil {
logging.LogErrorf("make import dir [%s] failed: %s", importDir, err)
ret.Code = -1
ret.Msg = err.Error()
return
}
writePath := filepath.Join(util.TempDir, "import", file.Filename)
defer os.RemoveAll(writePath)
writer, err := os.OpenFile(writePath, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
logging.LogErrorf("open import .zip [%s] failed: %s", writePath, err)
ret.Code = -1
ret.Msg = err.Error()
return
}
if _, err = io.Copy(writer, reader); err != nil {
logging.LogErrorf("write import .zip failed: %s", err)
ret.Code = -1
ret.Msg = err.Error()
return
}
writer.Close()
reader.Close()
notebook := form.Value["notebook"][0]
toPath := form.Value["toPath"][0]
// 准备解压路径
filenameMain := strings.TrimSuffix(file.Filename, filepath.Ext(file.Filename))
unzipPath := filepath.Join(util.TempDir, "import", filenameMain)
defer os.RemoveAll(unzipPath)
// 解压 writePath 的 zip 到 unzipPath
err = gulu.Zip.Unzip(writePath, unzipPath)
if err != nil {
logging.LogErrorf("unzip import .zip failed: %s", err)
ret.Code = -1
ret.Msg = err.Error()
return
}
// 调用本地导入逻辑
err = model.ImportFromLocalPath(notebook, unzipPath, toPath)
if err != nil {
ret.Code = -1
ret.Msg = err.Error()
return
}
}

View file

@ -320,6 +320,7 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/export/exportAttributeView", model.CheckAuth, model.CheckAdminRole, exportAttributeView)
ginServer.Handle("POST", "/api/import/importStdMd", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, importStdMd)
ginServer.Handle("POST", "/api/import/importZipMd", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, importZipMd)
ginServer.Handle("POST", "/api/import/importData", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, importData)
ginServer.Handle("POST", "/api/import/importSY", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, importSY)