思源笔记插件 版本 v0.9.32 需要思源 ≥ 3.8.0 桌面端(含桌面窗口) 纯前端 · 无内核侧代码 零外部依赖

把一篇文档,原样传上去。

一键将文档上传到 WebDAV / FTP / SFTP / 本地目录,导出格式三档可选:HTML (SiYuan) 整页、Markdown 正文 + 它引用到的资源,或 Word (.docx) 单文件;增量上传、试算、上传看板、改动检测、远端目录清理; 双链、块嵌入与图片资产全部保留。
本插件负责把文件传上去——把这个目录当站点对外提供,是你服务器的事。

点一下即可整段选中,自己按 Ctrl+C: siyuan-plugin-netglimmer-Upload

★推荐组合:WebDAV + HTML (SiYuan)

插件设置页的最上方钉的就是这一条(不是藏在说明里),理由与本页各处写的完全一致:

  • 完整性与风格——HTML (SiYuan) 是三档里唯一「一整页」的格式:明暗主题、代码高亮、侧边大纲、图片点击放大、双链与块嵌入都在,离线打开也是完整一页,还原度最高。
  • 兼容性——WebDAV 走的是普通 HTTP(PUT/DELETE/MKCOL/PROPFIND),浏览器、代理、防火墙都不额外挑;挂在子路径反代后面(https://host/dav)也照常工作。
  • 被验得最足——插件的端到端回归就是在这条链路上跑得最密:真实 IIS 与本机 nginx 各一遍,逐字节读回校验,连两家服务器的实测差异(409/403/递归删除)都写进了适配代码。

另两档各有取舍,不是不能用:Markdown 只有正文加它真正引用到的图,不带运行时、不注入大纲,能不能被浏览器直接打开取决于服务器 MIME;Word (.docx) 只有一个自包含文件,适合拿去 Word/WPS 继续编辑,但依赖内核自带的 pandoc、每次全量上传、页面上没有大纲与主题。FTP / SFTP / 本地目录都能配任一格式照常上传,只是 FTP 恒为单路串行、LIST 方言多,SFTP 仅支持密码认证。

定位

一个上传器,不是一个建站工具

这句话写在每一处界面文案里:插件不假装自己知道「这个目录能不能被访问」,它只承诺自己真正做到的那部分。

它做

  • 按选中的导出格式调用内核(HTML (SiYuan) 整页、Markdown 正文 + 它引用到的资源,或 Word (.docx) 一个自包含文件),把目录里的每个文件逐字节传到远端,传完做字节级校验。
  • 只传变化的部分(增量),HTML (SiYuan) 档还跳过重复的运行时文件(Word 档只有一个文件,无事可省,每次全量);同名文档各占各目录,靠归属标记互不覆盖。
  • 维护一份上传看板:每条记录可以重传、试算、删除远端文件、删除记录。
  • 检测哪些文档本地改了但还没再传,在文档树角标和看板上分别标出来。
  • 给 HTML (SiYuan) 档的页面注入侧边大纲(可拖拽调宽、左右停靠、折叠)和图片点击放大。

它不做

  • 不探测「这个地址能不能打开」——那会把上传器变成站点健康检查器,而它没有这个信息。
  • 不写剪贴板、不开新窗口、不自动复制地址,设置里也没有这个开关。
  • 不猜路径去删东西:记录里没有远端分段信息时,那一行根本不出现删除按钮,不会赌。
  • 不在内核里跑后端代码:backends 是空的,全部逻辑都在前端。
  • 不改变你的服务器配置,也不假装知道 IIS / nginx 各自的规则。
  • 不导出 PDF:思源内核没有 PDF 这条路,桌面端那份 PDF 是编辑器窗口打印出来的,插件进程拿不到(详见「边界」)。三档里能选的是 HTML、Markdown、Word。
能力

十件事,每件都能在看板里看到结果

↑一键上传当前文档

命令面板、文档树右键、编辑器标题栏右键、状态栏、可自定义快捷键五个入口同一个动作。右键的第一项永远是「Netglimmer 一键上传」,按今天的设置上传(是否含子文档由那个开关决定,不在菜单上分两条);这篇文档传过之后又改过的,下面多出一项 「检测到改动,重新上传」,按那条记录当初的协议与「含子文档」口径重传,而不是按今天的设置新开一次。判不准的一律不给第二项——没有成功记录、没存指纹、指纹查询失败、记录对应的远端已经删掉,都只留第一项,不摆一颗点下去只会把远端原样再盖一遍的按钮。

Δ增量上传

预检遍历一次同时算出「要传哪些」和「远端多了什么」;HTML (SiYuan) 档每次导出都附带的运行时文件按内容比对跳过(Markdown 档没有运行时,产物本来就只剩正文与图片;Word 档只有一个 .docx,增量无事可做、每次全量,历史记录里 reused 恒为 0),只改了几个字的重传就只剩那几个文件。

⌀试算(Dry run)

只统计「会传哪些文件、共多少字节、跳过多少」,一个字节都不写——回归里对此有专门的零写入断言。

▤上传看板

搜索文档名/路径/错误文本,按协议、结果、只看有改动筛选,点表头排序;列宽可拖动并按浏览器记忆,还会按当前界面上真实排出来的格子量出下限。

◔改动检测

用文档块索引(块数 + 最后更新时间)做指纹,一次批量查询比完全部记录;文档树角标区分「已上传」与「有改动未上传」。

×远端清理

「删除远端文件」删掉该文档自己的远端目录,文档与记录都保留并标记为「已删除远端」;另有「清理已删除文档的远端」批量处理当前筛选出来的那批。

⇄每协议一套配置

WebDAV / FTP / SFTP / 本地各自保存地址、端口、账号、前缀,切协议不用重填;FTP 与 SFTP 都有独立端口框,支持 host:2121 老写法。

✓测试连接

填完地址和账号先点「测试连接」再保存:WebDAV 用 PROPFIND 探可达性与认证(还会认应答里到底是不是 WebDAV 的 XML),再走一次写探针(MKCOL → PUT → GET 读回比对 → DELETE);FTP / SFTP 先登录,然后建目录、上传一个已知大小的临时探针、核对尺寸再删掉;本地档同样建目录 + 探针,量出来的是这个目录真的可写。SFTP 首次连接会在结果里给出主机密钥指纹并记录(TOFU),之后指纹变化直接拒绝,需要在「已知主机密钥 (SFTP)」一栏「清除全部」。

☰页面注入

侧边大纲可拖宽、左右停靠、目录折叠,正文居中,图片点击放大并支持触摸滑动;窄视口下大纲收进抽屉。

≡三种导出格式

设置里一个「导出格式」下拉框,与协议无关:HTML (SiYuan) 交思源自己那一整套静态页面(index.html + 运行时 + 引用的资源),还原度最高;Markdown 只交内核「导出 → Markdown」的那份正文(<文档名>.md,含前置元数据)和它真正引用到的 assets/——不带运行时、不注入大纲,产物小一到两个数量级;Word (.docx) 交内核(自带 pandoc,本机 3.8.6 是 3.10.1)那一个自包含文件,图片在包内的 word/media/ 里、与本地原件逐字节一致,「含子文档」在这档是真生效的(子文档并进同一个 word/document.xml),远端目录里除了它只剩一枚归属标记。三档里推荐 HTML (SiYuan),理由就是页首那块「推荐组合」讲的完整性 / 风格 / 被验得最足。

流程

一次上传从头到尾长什么样

取消是协作式的:阶段边界与每个文件之间检查一次,正在传的那个文件会传完才停——所以取消一次超大文件要等那一次传输结束。

1导出按选中的格式:HTML (SiYuan) 整页目录、Markdown 正文 + 引用到的资源,或 Word 的单个 .docx
2预检增量比对:哪些要传、远端多了什么
3并发传输按协议取并发上限,瞬时故障自动退避重试
4字节校验逐个文件比对远端字节,不只信 HTTP 状态码
5结果卡片路径整行可全选;只有一个按钮:打开上传看板

进度面板

右下角单块面板:阶段文字、按字节计算的进度条、当前文件名、节流刷新,以及一个「取消」。失败时错误里带着文件名与服务器给的原因(比如 413 会告诉你体积超限)。

半途取消之后

取消发生在写入口文件(index.html 或 <文档名>.md)之前 → 远端目录不完整,警告并留一条重传入口;发生在之后 → 远端已经是一份完整产物,按信息提示。两种情况都不会假装成功。

协议

四条链路,各自对着真服务器量过

FTP 与 SFTP 是插件内置的纯 JS 客户端,不需要任何外部程序。下面每一行都对应回归里的一次真机端到端。

WebDAV 默认协议

地址写法
根 URL,例如 https://example.com/dav;端口留在 URL 里,子路径(反代场景)不算错
传输通道
每个请求都走内核 /api/network/forwardProxy:HTTP 层恒 200,服务器真实状态码读 data.status,请求体统一 base64(3.8.6 的 text 分支是空实现)
验证过的服务器
IIS WebDAV 与本地 nginx(dav + dav_ext + Basic Auth)各一套端到端
实测到的差异
PROPFIND 方言、非递归 DELETE、目录标记的判定方式,都按两台服务器的真实响应适配,而不是按规范假设
清单里的转义
目录名里带 & 时,nginx 会在 PROPFIND 应答里把它写成 XML 实体,插件先还原再比对:不还原的话那个目录在比较键里根本不存在——增量上传会比不中,孤立清理还会把它当成旧残留删掉(IIS 走的是百分号编码,不需要这一步)
文件名适配
默认开启:NTFS 存不下的字符自动改成存得下的写法,并同步改写页面里的引用

FTP 纯 JS · PASV

地址与端口
主机(IPv4 / 域名 / IPv6,如 [::1])+ 独立端口框,空=21;192.168.1.10:2121 老写法仍然认
并发
恒为 1 路串行——单控制连接下多路 STOR 的应答会互相咬住,这是协议限制不是实现偷懒
中文文件名
探测服务器是否接受 UTF8,不接受则走 GBK 编码
列表方言
回归里用进程内假 FTP 覆盖 10 种服务器形态(unix / Windows 三种时间写法 / MLSD 三种应答 / 完全不认的方言 / 列表恒空 / 子目录列不全),专治「远端明明有文件却报全部缺失」的误判
数据连接
仍是 IPv4-only(PASV,无 EPSV);STOR 被拒绝、或 RETR 被服务器中途打断(425/426)时,那条已经建起来的数据连接一样要被关掉——失败一个漏一个,几百个文件之后控制连接就被踢了;而 425/426 也不算「读回来了」,半个文件不能当成校验通过

SFTP 纯 JS · SSH-2 · SFTP v3

认证
仅密码认证(不支持私钥 / passphrase)
主机密钥
TOFU:第一次连接记录指纹,之后不一致就拒连;换服务器后需在设置里「清除全部」
地址与端口
与 FTP 同一套端口字段,端口会进入指纹的键([::1]:2222),两个端口不冲突地各存一份
验证过的服务器
本机 OpenSSH(2222)端到端,含同名归属与删除远端文件两轮
断线之后
连接一断,在途的 SFTP 请求与「发出 INIT 后等 VERSION 回包」的那一步要当场被叫醒,它们各自挂着的 120 秒 / 15 秒计时器一起拆掉——否则宿主窗口会在一堆没人认领的定时器上空转,看着就是「断线以后卡了一会儿」

本地目录 无需服务器

地址写法
绝对路径(如 /srv/site/uploads 或 D:\www\upload),没有端口
用途
先在本机验证整套产物,再换成 WebDAV/FTP/SFTP 上传同一棵树
路径守卫
含 . / .. 段的配置直接被拒绝,解析到裸根目录的也拒绝;回归里用假上传器注入越界尝试,断言远端树一个字节没变
上传看板

每条记录都能就地处理,而不只是看

下面是按真实列结构与 当前版本的默认列宽(156 / 176 / 74 / 82 / 剩余 / 94 / 216,单位 px)画的示意,内容是示例数据。实际界面在弹窗里,列宽可拖,拖出的宽度按浏览器记忆。「结果」和「操作」这两列这里写成 minmax(95px, max-content) / minmax(218px, max-content)——地板取的是「这一列排成一行要多宽」(本机量出来 95 / 218),而不是默认列宽里那两个数(82 / 216):默认值只是起点,装不下时先被内容抬上去。示意页用 max-content 表达同一件事,插件本身不靠它,它在渲染之后用 Range 量出那个宽度、再把地板写进模板。两条路复现的是同一条规则:不许折行的列,地板由当前界面上真排出来的内容决定,宁可让相邻的弹性列收窄、宁可整表横向滚动,也不把徽标和按钮裁掉。

「详情」那一格前面钉着 本文 两个字,这不是装饰:同一次上传在这张表上有两个口径。格子里那个数只算本文自己的文件(正文 + 正文用到的资产),表格上方那句「实际传输 N 个文件 / 体积」才是这一次真正写进服务器的总量——它还含着每次导出都顺带带去的 stage/、appearance/ 运行时(示例里那篇「本文 128 文件」,实际传输可以是 571 个)。两个数并排着却不写口径,读起来就像账算错了,所以限定词直接进文案,鼠标停在「详情」表头上还能看到这句说明。

记录一多,找就变成了翻页与勾选的事。表格右下角是翻页条:「第 a–b 条 / 共 N 条」+「上一页 / 第 p / n 页 / 下一页」+「每页」下拉(10 / 20 / 50 / 100 / 全部,默认 20)。每页条数是习惯,和列宽、排序一样记在浏览器里,不随笔记同步;页码是这次浏览的临时意图,不记——切走页签、改搜索词、换协议或结果筛选、勾「只看有改动」都回到第一页,档位改大或筛选改短让页码越界时自动夹回真实最后一页。只有一页时上一页 / 下一页灰着但仍在那儿,按钮不随条数消失,工具条的位置就不会跳。要盯住的口径只有一条:翻页只决定这一屏画多少行——筛选、排序、勾选与三个批量按钮的作用范围始终是整个筛选结果,翻到第 3 页不会洗掉前两页的勾选,「删除所选 N 条」的 N 里也照数算着它们。

全选有两颗把手,作用范围写在各自的 tooltip 上:「时间」表头最前面那枚主复选框管当前这一页(三态——整页勾满才是勾上,勾了一半是半选,这一页全是「远端还挂着」的行就整个禁用),工具条上的「全选(筛选结果 N 条)」管整个筛选结果,包括翻页翻不到的那几页,按钮文字里那个 N 就是它这次能勾的条数,勾满之后自己翻成「取消勾选」。远端还挂着的行不进任何一颗把手:那条出路是旁边那个「删除远端文件」。

列宽:拖一列只动一列

每列表头右缘一根把手,拖完只改被拖那一列(放得下就照给,表格已经挤满时让无可让的那几个像素会当场折回去,而不是裁字);双击把手复位那一列,工具条「重置列宽」清掉记忆值。「操作」列的把手收在格子里,不会凭空撑出一条拖不动的横向滚动条。

下限来自实测,不来自某一种语言

时间 / 协议 / 结果 / 操作四列内容不许折行,它们的宽度下限在渲染时按当前界面上真排出来的格子量出来——换一种语言的字典,列会跟着变宽,而不是把字截成省略号。

删除记录有守卫

单条、批量、筛选后单条、筛选后批量四种都做得到;远端还挂着的行勾不动(勾选框禁用,tooltip 指向「删除远端文件」)。要删记录就先取消挂载,反过来也一样说得清。

安全

会删东西的地方,都有守卫

下面每一条都对应回归里的一个断言,不是「理论上应该会拦」。

①归属标记

每个上传目录里有一个 netglimmer-owner-*.json。两篇同名文档因此各占各目录(第二篇自动改名),删除远端时如果目录带着别人的归属标记,直接拒绝。

②不猜路径

「删除远端文件」只删该条记录里记录过的远端分段。记录里没有这个信息时,插件不会靠猜去删(也从不拿展示地址反推路径)——那种行根本不出现删除按钮,清理要手动做。

③空前缀警告

前缀留空会把文章直接铺到服务器根目录,这个开关会亮出来警告;地址字段还有实时格式校验,缺协议头、有多余空格都会按所选协议给出期望写法。

④路径加固

拒绝含 . / .. 段的配置路径,拒绝解析到裸根目录;上传前还会做字节级截断校验,避免写出半个文件。

⑤「清空远端旧目录」说清楚代价

默认开启,但开启增量时不会整树删除(那会连运行时一起删);只清理本文档目录里的孤儿资产与改名残留——切换导出格式后重传也算一次清理:上一个入口文件(index.html ↔ <文档名>.md ↔ <文档名>.docx)连同不再需要的运行时一起摘掉,不会留下两种格式混在一起的半套页面(三档来回切过也一样收干净,Word 档切走时那个 .docx 就是孤儿)。关掉它就是只追加模式——远端什么都不删。

⑥不碰剪贴板、不开窗口

上传成功后不自动复制任何地址,也没有「打开」按钮:那条地址只说明文件被放进哪个目录,说明不了有人把它当站点提供。看板与结果卡片里都没有任何剪贴板或 window.open 调用(回归里把剪贴板桩留在原地当绊线,谁再写就变红)。整个插件里只剩一处 window.open:文档树角标点开的是这篇文档记录在案的那个远端地址,带着 noopener,noreferrer(从思源里开出去的页面不许反手够到宿主窗口);而地址一旦与记录对不上(重传到别的目录、或改了文档名),这枚角标会被重建,不许留下一枚点开「文件早就不在那儿」的旧地址。

⑦校验说不出口的,写进记录

逐个确认文件时,服务器不答文件大小、或一次能读回的个数有上限,那几个文件就是没能确认过——插件不把它念成「远端缺失」,也不假装查过了:这个数会写进那条上传记录,看板上「本文 N 个文件」那一格悬停就能看到「另有 {n} 个文件本次未能逐个确认」。同样地,清单里列得出来、递归进去却列不出来的子目录(403 / 404)会把整份清单标成残缺,后续判定按残缺走。

⑧凭据是明文存的,这件事直说

服务器地址、用户名、密码以明文存在 data/storage/petal/siyuan-plugin-netglimmer-Upload/settings.json(本机可读)。思源没有提供系统钥匙串级别的凭据接口,而任何「加密」只要密钥还在本机,能读到你本机文件的程序同样能解密——所以这里不做假加密,只把话说清楚:不要把工作空间目录(或 data/storage/petal/)原样同步到公开位置或网盘;分享配置前手工删掉 settings.json 里的 password 字段;给上传用的账号只开目标子目录的写权限。两道配套的防泄漏:上传历史 history.json 不含密码,而控制台打印地址时先去凭据(思源的控制台是所有插件共用的,4xx/5xx 那几行不受调试开关控制、始终记录)。设置页每个输入框都向浏览器表态(name="netglimmer-upload-<键名>" + 明确的 autocomplete:密码框 new-password、用户名 username、地址 url,其余 off)——浏览器「好心」预填一个旧凭据比留空更难查,因为报出来的错跟你实际输入的内容毫无关系。

质量

它是怎么被测过的

回归套件不写「应该没问题」:涉及远端的每一步都打到真服务器,涉及排版的每一步都在真 Chromium 里读盒模型。

31
回归步骤,一次全绿
1155
真排版断言 · 看板与设置弹窗
297
看板视图断言 · 列宽、筛选、翻页与全选
109
项断言专测 Markdown / Word 档产物形状
4
种协议各一遍端到端
241
个界面文案键 · 用到的 230 个全在其中,中英键集一致

真服务器,不是模拟

WebDAV 打真实 IIS 与本机 nginx(各测各的方言差异),FTP 打 vsftpd(2121),SFTP 打 OpenSSH(2222),本地目录走真实文件系统;另有进程内故障注入验证「瞬时错误重试成功 / 403 快速失败 / 重试入口」。

  • 上传链路测完自己收摊:删掉测试前缀并确认 PROPFIND 404 才算通过。
  • 取消上传在三种时机各测一遍:导出中(远端没动过)、上传中(远端残缺,警告并留重传入口)、入口文件已传完(远端其实是一份完整产物,就按信息提示,不喊不完整)。

排版是被量出来的

加载思源真实的 base.css 与 daylight 主题,配一份忠实移植宿主行为的对话框,中文字典下 1600/1200/1000/800px、英文字典下 1600/1000px 各量一遍:内容不溢出、每个按钮 clip === 0、不许折行的列不得低于实测单行宽、拖把手那一下也真拖两回(宽档与窄档各一次):弹性列还让得动时正好宽 60px,它已经让到地板时按剩得出来的空间收窄,两种情况下其余固定列都一像素不动、也没有任何一格被裁字。

  • 这套测量就是因为一句「设置项都溢出了」的报告加进套件的,此后界面尺寸问题靠测量而不是争论。
  • 像素数来自 daylight 主题 + 默认字号;换主题或缩放会得到另一组数,所以断言写成不变式。
安装

三步跑起来

项目地址:github.com/netglimmer/siyuan-plugin-netglimmer-Upload

1放入插件目录解压 siyuan-plugin-netglimmer-Upload 到 data/plugins/,或从集市安装
2启用并设置工具箱里启用 → 打开「Netglimmer 上传」设置:面板最上方就写着推荐组合 WebDAV + HTML (SiYuan);选协议、填地址与端口、填远端子目录
3先试算再传不确定远端会怎样,就先点「试算」;它只报数,不写一个字节

包内有什么

index.js插件全部逻辑(由 src/core.js + vendored 段拼装产物)
plugin.jsonv0.9.32 · minAppVersion 3.8.0 · backends 空
icon.png512×512 8bit RGBA,集市卡片图标(思源只认插件根目录下的位图)
i18n/zh_CN.json + en_US.json,各 241 键(界面文案引用到其中的 230 个),两份键集一致
README.md / README_zh_CN.md中英各一份:配置逐项说明、服务器端注意、回归覆盖与已知限制

只读写当前插件标识

设置与上传历史只存在当前标识 siyuan-plugin-netglimmer-Upload 自己的 settings.json / history.json 里,不读别的插件的存储,也不替任何别处的配置做转换:这个标识下没有数据,就是一份空设置加空历史,第一次上传时把服务器/账号填一遍即可。

  • 配置里只有一种形状:每个协议各自一格 server / port / username / password / prefix,切换协议互不覆盖;顶层没有平铺的凭据字段,读取时也只认当前协议那一格。
  • 残留的 copyOnPublish 开关会被识别并丢弃,且不会被静默写回。
  • 历史记录里带着 pub 标记与本文自有文件数;能定位远端目录的记录还存着远端分段(rootSegs),「删除远端文件」只认它、不从展示地址反推——没有分段信息的行不出现删除按钮,界面上没有「这种字段可能是老数据没有」的猜测分支。
边界

这些它做不到,也不假装做得到

没有 PDF 档,原因是内核不给这条路

思源的内核导出接口里没有 PDF,只有一个 processPDF——那是 pdfcpu 对已有 PDF 做后处理的工具(加水印、加书签、把链接指向的资产嵌进去),它自己不排版,不先把 PDF 传进去就没有 PDF 出来。桌面端「导出 → PDF」的字节来自 Electron 主进程的 printToPDF:插件代码跑在渲染进程,要调它得走私有 IPC,而且要求真的开出一个可见的编辑器窗口(远程内核模式下这条路被直接忽略)。所以这一档不是「还没做」,是插件这一侧没有可复用的 PDF 能力。替代做法写在设置项的说明里:在思源里手动导出 PDF,或者传 Word 档那份 .docx 之后用 Word 另存为 PDF。

Markdown 档没有「含子文档」这一档

内核的 exportMdContent 只接受单个文档 ID。所以选 Markdown 时,设置里的「一键上传时包含子文档」自动不生效,历史记录里写的也是「不含子文档」——写真实产物,而不是写你那个此刻无意义的开关。HTML 与 Word 两档的「含子文档」都是真生效(Word 实测把子文档并进同一个 word/document.xml);加密笔记本不支持上传(内核会拒绝明文导出)。

Word 档的三条代价

① 它依赖思源自带的 pandoc(本机 3.8.6 随包带 3.10.1):内核拒绝时插件把内核原文摊给你,不会另找个排版器凑一个「看着像 Word」的文件——那种产物的字形、分页、目录都不会对得上,比失败更难排查。② 它需要内核报告的绝对工作区路径来落临时文件:拿不到就当场失败并说明原因,绝不退回相对路径(相对 savePath 按内核工作目录解析,实测会把产物写进思源的安装目录)。③ 每次上传都是全量:只有一个文件、没有可复用的运行时,历史记录里 reused 恒为 0;pandoc 会把生成时间写进包内属性文件,实测同一篇文档隔一秒再导出会差一个字节,所以「重传后字节变了」不等于内容变了——改动检测用的是文档内容指纹,不是产物哈希。

Markdown 能不能被读者直接打开,取决于你的服务器

插件把 <文档名>.md 放上去这件事是真的——这一条走的是插件自己的上传链路,在真实 IIS 上端到端测过(PUT 201、PROPFIND 列得出、远端字节数与「按安全名改写过的正文」完全一致)。但 真实 IIS 对它的 HTTP GET 回 404——静态文件模块只服务 MIME 清单里配过的扩展名,.md 默认不在其中;本机 nginx 回 200 application/octet-stream,能下载、不会当网页渲染。要在浏览器里读,请在 IIS 补一条 .md → text/markdown(或 text/plain)的 MIME 映射;不然就把 Markdown 档当作「喂给静态站点生成器 / 本地阅读器」的产物。Word 档没有这个问题:同一台 IIS 对 .docx 的 GET 实测回 200 并带 Office 的 MIME 类型,本机 nginx 同样 200,浏览器行为是下载或交给 Word——这本来就是这一档想要的效果。

SFTP 只有密码认证

不支持私钥与 passphrase。主机密钥是 TOFU 策略:第一次连接记录指纹,之后不一致就拒绝连接;换了服务器需要手动清除已记录指纹。

并发与体积上限

并发按协议取上限(WebDAV 6 / SFTP 4 / 本地 4,FTP 恒为 1 路串行——单控制连接下多路 STOR 的应答会互相咬住),设置里可以手动覆盖成 1–16。单文件默认上限 64 MB(可调,0=不限制),超限文件跳过并明确报错——因为整文件要读进内存做字节校验;WebDAV 的每一次读写都只有内核 forwardProxy 这一条通道(浏览器发不出 PROPFIND/MKCOL,也带不上跨域 Basic Auth,所以没有「浏览器直连」可退),文件是先 base64 再交给内核转发的,体积约 1.33 倍——这道上限是「内存 + 内核通道」的合计成本。FTP / SFTP 走桌面端内置 Node 的直接 socket,不经过这条通道,因此不吃这份膨胀,但需要桌面端能直连服务器端口。

改动检测的两个已知口径

检测基于文档块索引(块数 + 最后更新时间),所以「只改了块属性、块数与时间都没动」这种情况看不出来。进回收站的文档不会被认成已删除——实测内核里回收站文档的 blocks 行仍在,指纹查询会回答「它还在」。

取消是协作式的

正在上传的那一个文件会先传完才停,所以取消一次超大文件的上传时要等那一次传输。中途掐断在途请求会留下半个文件,而插件的目标是逐字节可验证,所以选择不掐。

界面尺寸按真实排版量

列宽下限来自渲染时实测,测量范围限定在本次渲染的前 60 行(把一次渲染的成本钉成常数,不随历史记录条数增长)。思源主题、字号或缩放变化会得出另一组数——放不下时表格横向滚动是设计选择,而不是把字裁掉。

不提供站点能力

把上传目录变成可访问的站点是你的服务器配置(IIS / nginx / 反代规则)决定的,本插件不探测、不保证、也不替你猜——这一点和它的名字一样,写在每一处界面文案里。