为什么不该把文档上传到云端

上传一份文件,等于在别人的磁盘上留下副本。本文拆解文件上传之后经过哪些存储、为什么删除不等于撤回,并给出一套十分钟就能自己动手的验证方法。

作者 SecureRAG Team · · 10 分钟阅读

上传一份文档,就是在别人的机器上生成一份副本,此后它按对方的规则保存多久,你说了不算。文件离开你设备的那一刻,主动权就交出去了;下面讲清副本会变成什么、删除为什么救不回来,以及一个工具到底是不是本地运行该怎么自己验。

上传之后,文件经历了什么

在浏览器里,上传看起来只是一个动作。到了服务端,它会变成好几份各自独立、各自计时的数据。

一、请求本身。 文件字节经 TLS 到达某个入口,入口前面的网关、负载均衡和 CDN 会记访问日志:时间、来源 IP、UA、请求路径、账号、状态码、字节数。一些日志管道为了排查故障或识别滥用,会按比例抽样保留请求正文。

二、对象存储。 文件通常被写进 blob 存储,成为一条带 bucket、key、存储级别和版本号的对象。存储里没有目录,界面上那个“文件夹”只是数据库里的一列。

三、抽出来的纯文本。 只要产品提供全文搜索、摘要或“和文档对话”,你的文件就被解析过,文本单独存了一份。抽取后的纯文本比 PDF 更容易被批量查看,而它属于第二份副本,删除按钮未必覆盖得到。

四、备份与副本。 对象存储多半开了版本管理,快照周期按平台自己的排期跑,和你何时删除没有关系;跨区复制还会把对象再写一份到别的地方。删除常常只是写入标记,旧版本要等保留期结束才真正消失。

五、用于改进模型或训练的设置。 个人版套餐经常默认勾选“帮助改进服务”,开关藏在设置深处;企业版则多是用合同条款排除。适用哪一条,取决于你所在的套餐,以及数据被使用当天生效的条款——它未必等于你上传当天生效的条款。

六、风控与客服。 多数服务商保留对自动系统标记的内容进行人工或模型复核的权利。工单是另一条路径:附件一般落在另一个系统里,保留策略另算。

上面这些没有一条需要有人怀有恶意,它就是托管服务的常态。也正因如此,“我们非常重视隐私”回答不了真正的问题——你们的员工能不能打开我的文件。

删除不等于撤回

大多数人的心理模型是:文件放上去了,删掉就等于收回来。实际模型是:别人的磁盘上已经多了一份副本,删除只是把指向它的一条记录拿掉。

在云端把文档从列表里删掉,下面这些通常纹丝不动:

  • 之前生成的纯文本、缩略图、预览;
  • 由它算出的向量和搜索索引;
  • 保留期内的备份快照;
  • 被抽样的请求日志正文;
  • 客服工单里的附件;
  • 你本机浏览器在会话期间缓存的那一份。

所以决策点不在“以后再删”,因为副本一旦存在,这个问题就没有第二次机会。真正的决策点是“这份副本要不要产生”,而且只在点击上传的那一秒有效。

还有一个很少被提到的后果:上传是个法律动作。你使一份内容出现在了第三方的设施上,在公司内部,这可能触发一连串义务——登记、评估,以及万一泄露时的通报责任。文件留在设备上的工具不会产生这一环。

怎么读懂一套隐私说法

这个领域的文案高度趋同,常见的几句可以这样翻译:

说法 通常的含义 它没有回答的问题
传输与存储全程加密 链路是 TLS,磁盘是加密的 运营方自己能不能读——密钥在他们手里
不会用你的数据训练 一项靠流程执行的策略 架构上是否做不到;条款一改,策略就变
随时可删除 从你的可见范围里移除 保留期内的版本、副本和派生文本按对方排期走
隐私优先设计 一般指权限控制和最小化 网络层面到底有没有东西离开你的机器

唯一经得起推敲的说法,是你能自己验证的那一种。对于在浏览器里跑的页面,验证成本很低。

十分钟,自己动手验一遍

不用读源码,也不用等审计报告,拿你现在用的工具直接试。

  1. 新开一个标签页,按 F12,切到“网络”,勾上“保留日志”。

  2. 刷新页面等它初始化。真正本地的工具只会出现少量本方资源(htmljswasmcss),首次使用时多一次模型下载——一个 GET 请求,路径里是模型文件名,例如 bge-small-zh-v1.5。注意它的形态:只有文件名,没有你的内容。

  3. 趁面板还在录制添加一份文档,按体积排序找有没有几 MB 的 POST 或 PUT 正文。上传在这个面板里藏不住。

  4. 连问三四个问题。本地检索只读取本机索引,这一步不应该出现新请求;如果回答是远端生成的,每个答案都得发一次请求。

  5. 现在断网——把网络面板的节流改成“离线”,或者直接禁掉网卡——再问一个问题。断网状态下仍能给出带出处的答案,说明检索确实跑在你这边。

  6. 想更严密,就把浏览器那几个网络 API 套一层。在使用前,到控制台执行:

    const _fetch = window.fetch;
    window.fetch = (...a) => { console.log('fetch', a[0]); return _fetch(...a); };
    const _open = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function (m, u, ...r) { console.log('xhr', m, u); return _open.call(this, m, u, ...r); };
    const _beacon = navigator.sendBeacon?.bind(navigator);
    navigator.sendBeacon = (u, d) => { console.log('beacon', u, d); return _beacon(u, d); };

    之后每一次外发调用都会打印一行。特别要盯 sendBeacon,它在页面卸载时仍会执行,是“关标签页时顺手把数据送走”最常用的接口。

  7. 想看清所有标签页而不只是一个,就让浏览器走本地代理(例如 mitmproxy),一次性完成“导入文档 + 提一个问题”,再翻会话日志。发往统计服务或字体服务商的请求,在日志里和别的东西一样清楚。

你要的是一个否定结果:没有以你的文档为正文的请求,提问时不新开 WebSocket,卸载时没有 beacon。一个真本地的工具仍然可能加载统计脚本,真正要问的是你的内容有没有出去。

什么时候本地处理确实不合适

躲开上传不是零成本的,硬说没代价就不诚实了。本站引擎完全在标签页里跑,也就有硬上限:单文件 25MB、单库 40 份、总量 200MB、单库 20,000 块,手机上界面限制 10 份。加密 PDF 读不了,没有文字层的扫描件得先做 OCR,旧版 .doc 直接拒绝。如果你要的是团队共用的索引、可追溯的审计链,或者几千份扫描件的资料库,那是托管服务能做的事,一个浏览器标签页做不到。

所以判断范围其实很窄:一份你只是要翻阅的合同、一份自己整理的体检报告、面试材料、薪酬表格——这些场景里副本本身就是风险,本地方案除了多花几分钟配置,没有任何损失。反过来,一份下周需要四十个同事一起改的文档,副本本身才是功能。