diff --git a/app/guide/20210808180117-6v0mkxr/20200923234011-ieuun1p/20210808180303-xaduj2o/20201227201128-m1wrouw.sy b/app/guide/20210808180117-6v0mkxr/20200923234011-ieuun1p/20210808180303-xaduj2o/20201227201128-m1wrouw.sy index 5e5b8f20c..39dccb2f8 100644 --- a/app/guide/20210808180117-6v0mkxr/20200923234011-ieuun1p/20210808180303-xaduj2o/20201227201128-m1wrouw.sy +++ b/app/guide/20210808180117-6v0mkxr/20200923234011-ieuun1p/20210808180303-xaduj2o/20201227201128-m1wrouw.sy @@ -858,7 +858,7 @@ "Children": [ { "Type": "NodeText", - "Data": "Does not support exporting to formats such as PDF, HTML, and Word" + "Data": "Does not support exporting to formats such as PDF and Word" } ] } diff --git a/app/guide/20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180321-hbvl5c2/20201227173504-847cs1q.sy b/app/guide/20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180321-hbvl5c2/20201227173504-847cs1q.sy index be0d07db4..bc597a26f 100644 --- a/app/guide/20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180321-hbvl5c2/20201227173504-847cs1q.sy +++ b/app/guide/20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180321-hbvl5c2/20201227173504-847cs1q.sy @@ -866,7 +866,7 @@ "Children": [ { "Type": "NodeText", - "Data": "不支持导出 PDF、HTML 和 Word 等格式" + "Data": "不支持导出 PDF 和 Word 等格式" } ] } diff --git a/app/guide/20211226090932-5lcq56f/20211226115423-d5z1joq/20211226121203-rjjngpz/20211226122459-08mi5cq.sy b/app/guide/20211226090932-5lcq56f/20211226115423-d5z1joq/20211226121203-rjjngpz/20211226122459-08mi5cq.sy index a81dc63c3..5ec27f50e 100644 --- a/app/guide/20211226090932-5lcq56f/20211226115423-d5z1joq/20211226121203-rjjngpz/20211226122459-08mi5cq.sy +++ b/app/guide/20211226090932-5lcq56f/20211226115423-d5z1joq/20211226121203-rjjngpz/20211226122459-08mi5cq.sy @@ -829,7 +829,7 @@ "Children": [ { "Type": "NodeText", - "Data": "不支援導出 PDF、HTML 和 Word 等格式" + "Data": "不支援匯出 PDF 和 Word 等格式" } ] } diff --git a/app/guide/20240530133126-axarxgx/20240530101000-4qitucx/20240530101000-g3ugxml/20240530101000-f16hpct.sy b/app/guide/20240530133126-axarxgx/20240530101000-4qitucx/20240530101000-g3ugxml/20240530101000-f16hpct.sy index 7f03f6270..7bf099288 100644 --- a/app/guide/20240530133126-axarxgx/20240530101000-4qitucx/20240530101000-g3ugxml/20240530101000-f16hpct.sy +++ b/app/guide/20240530133126-axarxgx/20240530101000-4qitucx/20240530101000-g3ugxml/20240530101000-f16hpct.sy @@ -978,7 +978,7 @@ "Children": [ { "Type": "NodeText", - "Data": "PDF、HTML、Word などの形式でのエクスポートはサポートしていません" + "Data": "PDF や Word などの形式へのエクスポートはサポートされていません" } ] } diff --git a/app/src/menus/commonMenuItem.ts b/app/src/menus/commonMenuItem.ts index 3263c5498..04671a826 100644 --- a/app/src/menus/commonMenuItem.ts +++ b/app/src/menus/commonMenuItem.ts @@ -767,7 +767,8 @@ export const exportMd = (id: string) => { keepFold: localData.keepFold, merge: localData.mergeSubdocs, }, async response => { - const html = await onExport(response, undefined, {type: "pdf", id}); + const servePath = window.location.protocol + "//" + window.location.host + "/"; + const html = await onExport(response, undefined, servePath, {type: "pdf", id}); if (isInAndroid()) { window.JSAndroid.print(html); } else if (isInHarmony()) { diff --git a/app/src/protyle/export/index.ts b/app/src/protyle/export/index.ts index 26edcda10..306a71cdf 100644 --- a/app/src/protyle/export/index.ts +++ b/app/src/protyle/export/index.ts @@ -43,7 +43,7 @@ export const saveExport = (option: IExportOptions) => { merge: true, savePath: "" }, async exportResponse => { - const html = await onExport(exportResponse, undefined, option); + const html = await onExport(exportResponse, undefined, "", option); fetchPost("/api/export/exportBrowserHTML", { folder: exportResponse.data.folder, html: html, @@ -684,7 +684,7 @@ const getExportPath = (option: IExportOptions, removeAssets?: boolean, mergeSubd } afterExport(exportResponse.data.path, msgId); } else { - onExport(exportResponse, savePath, option, msgId); + onExport(exportResponse, savePath, "", option, msgId); } }); } @@ -692,7 +692,7 @@ const getExportPath = (option: IExportOptions, removeAssets?: boolean, mergeSubd }; /// #endif -export const onExport = async (data: IWebSocketData, filePath: string, exportOption: IExportOptions, msgId?: string) => { +export const onExport = async (data: IWebSocketData, filePath: string, servePath: string, exportOption: IExportOptions, msgId?: string) => { let themeName = window.siyuan.config.appearance.themeLight; let mode = 0; if (["html", "htmlmd"].includes(exportOption.type) && window.siyuan.config.appearance.mode === 1) { @@ -700,8 +700,6 @@ export const onExport = async (data: IWebSocketData, filePath: string, exportOpt mode = 1; } const isDefault = (window.siyuan.config.appearance.mode === 1 && window.siyuan.config.appearance.themeDark === "midnight") || (window.siyuan.config.appearance.mode === 0 && window.siyuan.config.appearance.themeLight === "daylight"); - const isLocalExport = typeof filePath !== "undefined"; - const servePath = isLocalExport ? "" : window.location.protocol + "//" + window.location.host + "/"; let themeStyle = ""; if (!isDefault) { themeStyle = ``; diff --git a/kernel/cache/asset.go b/kernel/cache/asset.go index 63cb231bc..fa623de9a 100644 --- a/kernel/cache/asset.go +++ b/kernel/cache/asset.go @@ -28,14 +28,60 @@ import ( "github.com/siyuan-note/siyuan/kernel/util" ) +type AssetHash struct { + Hash string `json:"hash"` + Path string `json:"path"` +} + +var ( + assetHashCache = map[string]*AssetHash{} + assetHashLock = sync.Mutex{} +) + +func RemoveAssetHash(hash string) { + assetHashLock.Lock() + defer assetHashLock.Unlock() + + delete(assetHashCache, hash) +} + +func SetAssetHash(hash, path string) { + assetHashLock.Lock() + defer assetHashLock.Unlock() + + assetHashCache[hash] = &AssetHash{ + Hash: hash, + Path: path, + } +} + +func GetAssetHash(hash string) *AssetHash { + assetHashLock.Lock() + defer assetHashLock.Unlock() + + for _, a := range assetHashCache { + if a.Hash == hash { + if filelock.IsExist(filepath.Join(util.DataDir, a.Path)) { + return a + } + + delete(assetHashCache, hash) + return nil + } + } + return nil +} + type Asset struct { HName string `json:"hName"` Path string `json:"path"` Updated int64 `json:"updated"` } -var assetsCache = map[string]*Asset{} -var assetsLock = sync.Mutex{} +var ( + assetsCache = map[string]*Asset{} + assetsLock = sync.Mutex{} +) func GetAssets() (ret map[string]*Asset) { assetsLock.Lock() diff --git a/kernel/model/assets.go b/kernel/model/assets.go index 3e55a3a09..cdc5a951f 100644 --- a/kernel/model/assets.go +++ b/kernel/model/assets.go @@ -51,6 +51,19 @@ import ( "github.com/siyuan-note/siyuan/kernel/util" ) +func GetAssetPathByHash(hash string) string { + assetHash := cache.GetAssetHash(hash) + if nil == assetHash { + sqlAsset := sql.QueryAssetByHash(hash) + if nil == sqlAsset { + return "" + } + cache.SetAssetHash(sqlAsset.Hash, sqlAsset.Path) + return sqlAsset.Path + } + return assetHash.Path +} + func HandleAssetsRemoveEvent(assetAbsPath string) { removeIndexAssetContent(assetAbsPath) removeAssetThumbnail(assetAbsPath) @@ -648,6 +661,7 @@ func RemoveUnusedAssets() (ret []string) { hash, _ := util.GetEtag(p) hashes = append(hashes, hash) + cache.RemoveAssetHash(hash) } } @@ -703,6 +717,7 @@ func RemoveUnusedAsset(p string) (ret string) { hash, _ := util.GetEtag(absPath) sql.BatchRemoveAssetsQueue([]string{hash}) + cache.RemoveAssetHash(hash) } if err = filelock.Remove(absPath); err != nil { diff --git a/kernel/model/upload.go b/kernel/model/upload.go index 53b1f3cb9..49a896a16 100644 --- a/kernel/model/upload.go +++ b/kernel/model/upload.go @@ -29,7 +29,7 @@ import ( "github.com/gin-gonic/gin" "github.com/siyuan-note/filelock" "github.com/siyuan-note/logging" - "github.com/siyuan-note/siyuan/kernel/sql" + "github.com/siyuan-note/siyuan/kernel/cache" "github.com/siyuan-note/siyuan/kernel/treenode" "github.com/siyuan-note/siyuan/kernel/util" ) @@ -90,9 +90,9 @@ func InsertLocalAssets(id string, assetAbsPaths []string, isUpload bool) (succMa return } - if existAsset := sql.QueryAssetByHash(hash); nil != existAsset { + if existAssetPath := GetAssetPathByHash(hash); "" != existAssetPath { // 已经存在同样数据的资源文件的话不重复保存 - succMap[baseName] = existAsset.Path + succMap[baseName] = existAssetPath } else { fName = util.AssetName(fName, ast.NewNodeID()) writePath := filepath.Join(assetsDirPath, fName) @@ -105,7 +105,10 @@ func InsertLocalAssets(id string, assetAbsPaths []string, isUpload bool) (succMa return } f.Close() - succMap[baseName] = "assets/" + fName + + p := "assets/" + fName + succMap[baseName] = p + cache.SetAssetHash(hash, p) } } IncSync() @@ -197,9 +200,9 @@ func Upload(c *gin.Context) { break } - if existAsset := sql.QueryAssetByHash(hash); nil != existAsset { + if existAssetPath := GetAssetPathByHash(hash); "" != existAssetPath { // 已经存在同样数据的资源文件的话不重复保存 - succMap[baseName] = existAsset.Path + succMap[baseName] = existAssetPath } else { if skipIfDuplicated { // 复制 PDF 矩形注解时不再重复插入图片 No longer upload image repeatedly when copying PDF rectangle annotation https://github.com/siyuan-note/siyuan/issues/10666 @@ -310,7 +313,9 @@ func Upload(c *gin.Context) { os.RemoveAll(tmpDir2) } - succMap[baseName] = strings.TrimPrefix(path.Join(relAssetsDirPath, fName), "/") + p := strings.TrimPrefix(path.Join(relAssetsDirPath, fName), "/") + succMap[baseName] = p + cache.SetAssetHash(hash, p) } } diff --git a/kernel/util/etag.go b/kernel/util/etag.go index 2152966f9..9c9fbee86 100644 --- a/kernel/util/etag.go +++ b/kernel/util/etag.go @@ -80,7 +80,6 @@ func BlockCount(fsize int64) int { } func CalSha1(b []byte, r io.Reader) ([]byte, error) { - h := sha1.New() _, err := io.Copy(h, r) if err != nil {