合同附件当天上传还能预览,第二天同事从另一台机器下载却说文件不存在,该先查存储位置还是先查下载接口?
多数情况下,这类问题不是上传接口坏了,也不是下载接口丢了权限,而是文件只写在某一台实例的本地磁盘上:上传落到 A,下载被分到 B,B 上自然没有这个文件。先到另一台机器的上传目录看有没有同名文件,几分钟就能把方向分清;要不要单独搭文件服务,取决于实例数会不会增加、附件是否承担业务凭证角色,而不是单看文件大小。
先分清是没传上去,还是传到了别的机器
附件类问题和普通接口问题的排查路径不一样。上传接口返回 200、文件大小对得上、当场点预览还能打开,说明写入这一步基本是通的;真正的分歧点在于文件被写到哪台机器上、下载时又去哪台机器取。本地磁盘存储把文件和实例绑在一起,而多实例部署默认每台实例无差别,这两件事天然冲突。
- 刚传完能看,过一阵就 404:下载请求被负载均衡分到了另一台实例,那台上没有这个文件。
- 一部分用户打不开:取决于请求落到哪台,实例越多,命中率越低。
- 发版后历史附件集体消失:文件写在容器可写层或代码目录下,容器重建即清空。
- 反例:如果上传当场就报错,或者所有机器、所有用户都下载失败,更像目录权限、磁盘写满、路径拼接问题,不必往存储位置上套。
文件在不在,是由写它的那台机器决定的;只要实例不止一台,本地磁盘就不再是一个可靠的存储位置。这句话可以作为判断这类问题的分界线。
按写入、存放、读取、清理四段排查
文件类故障通常落在写入、存放、读取、清理四段之一。按链路走一遍比反复改下载代码快,因为每一段都能用一条命令或一次操作验证,不需要猜。之所以这样划分,是因为这四段的证据互不重叠,确认完就能排除掉一大半可能。
- 写入段:在上传代码里把最终落盘路径打印出来,确认是绝对路径还是相对路径、是否指向容器内临时目录。相对路径在不同工作目录下会写到不同地方,这是常见的第一层坑。
- 存放段:确认部署形态——几台实例、是不是同一个挂载、容器重建后目录是否还在。这一步的结论决定后面所有方案。
- 读取段:看下载请求经过谁——网关、静态托管、CDN 还是后端接口,以及最终落到哪台实例。注意 CDN 可能缓存了之前的 404。
- 清理段:确认有没有定时任务在清理临时目录,是否把正常附件一并扫掉,避免修好之后又被清空一次。
排查顺序应该反过来:先确认文件在不在,再谈下载逻辑;文件不在,改下载代码是白改。实际操作中,常见情况是在读取段折腾很久,回到存放段一看实例早就两台了,问题从一开始就不在读取逻辑里。
三档存储的适用边界与经验区间
选哪一档取决于三件事:实例数会不会变、附件是不是业务凭证、需要留存多久。文件总量反而排在后面,几 GB 的文件放在共享挂载上完全跑得动,而实例一变,本地磁盘立刻不可用。下面按 2026 年常见交付经验整理对比,成本与工期都是经验区间,具体以实际环境和云厂商当期价目为准。
- 单机本地磁盘:适合单实例、纯内网、文件总量在几百 MB 到几十 GB 区间;改造成本接近于零;代价是扩容即失效,备份脚本要单独写。
- 共享挂载(NFS 或云盘挂载):适合 2~5 台实例、内网环境;改造量常见 1~3 人日;代价是 IO 抖动和权限映射,挂载短暂掉线时上传会超时。
- 对象存储:适合多实例、对外访问、需要长期留存或外链分享;改造量常见 3~10 人日,包含签名链接、权限、老文件迁移;费用按量计,存储费常见在每 GB 每月 0.1 元量级,流量与请求费另计。
对象存储不是更先进,只是把有状态的存储从应用实例里剥离出去,代价是引入密钥管理、网络连通和按量计费。能不能继续用本地磁盘,判断标准不是文件多少,而是实例数会不会变多。
哪些情况可以继续用本地磁盘,哪些不宜再拖
这一节写清晰一点,避免为了架构正确而上不必要的组件。很多内网项目只有一台应用机,附件是临时导入的表格,这种场景上对象存储,反而会带来出网不通、密钥轮换、跨域配置等一串新问题。
- 可以继续用本地磁盘:单实例部署、纯内网、附件只是临时导入导出、丢了也能重传、交付周期很紧。
- 建议尽快改造:已经或计划多实例、容器化部署、附件承担业务凭证角色(合同、发票、验收单)、需要对外分享链接或留存年限要求。
- 不必上对象存储:文件总量在几 GB 以内且长期只有一台机器,硬上会增加运维面。
边界可以概括成一句:如果系统未来一年内会加第二台实例,本地磁盘就不太适合作为长期方案;如果确定长期单机,做好目录备份和磁盘监控就够用。附件属于业务凭证时,丢文件的代价通常高于存储成本差异,这一档不宜只按省钱来决策。
交付现场:两台虚机、不能出网、附件是扫描件
在项目交付里常见的一种约束是:客户内网不能出网,只给两台虚机,预算有限,附件是扫描件,单份从几百 KB 到十几 MB 不等。按这类条件,常见做法是先挂共享盘,把上传目录从代码目录里独立出来,下载统一走后端代理做权限校验。代价也随之而来——共享盘 IO 抖动,大文件上传偶发超时,后来补了分片上传和超时重试,前后返工接近一周。按 2026 年常见交付经验,这类内网项目改造量常见在 2~5 人日区间,返工多来自共享盘 IO 抖动和大文件超时;先按约束选档,比先定技术栈省事得多。
上线前后容易漏掉的检查项
上线前后容易漏掉的不是大方案,而是几个小口径。下面这些检查项不需要额外工具,按现有环境就能核对。
- 容器内直接写文件:没有挂持久卷,重建即丢,看起来像偶发丢附件。
- 中文文件名编码不一致:不同机器、不同挂载之间出现同名覆盖或下载名乱码。
- 下载直接暴露目录:缺少鉴权,链接一旦外传就收不回来。
- 缩略图在读取时同步生成:多台机器各生成一份,磁盘翻倍且各机时间点不一致。
- 只备份数据库不备份附件目录:恢复之后记录在、文件不在。
- CDN 缓存了 404:文件补回去之后页面仍然打不开,需要手动刷新缓存。
合格口径可以量化成四条:上传完成后从另一台实例能下载成功;发版重建后历史附件仍可下载;数据库记录与附件文件能按月对账;单文件上传失败时有明确错误码和重试入口。这四条都过得去,才算把存储位置这层真正解决,而不是碰巧这台机器上有文件。
常见问题
只有两台服务器,能不能让上传目录互相同步一下?
可以应急,但同步存在时间窗口,刚传完立刻下载仍可能失败;对实时性要求不高的场景可用,正式方案更常见的是共享挂载或对象存储。
换成对象存储后,老附件打不开处理起来麻烦吗?
常见做法是保留原路径映射,读到老记录时回源旧地址,或做一次性迁移脚本;迁移期间两套读取逻辑并存,不要直接切换。
附件下载每次都要走后端接口吗?
涉及权限校验或计量的要走后端签发临时链接;纯公开资源可以直接由对象存储或 CDN 提供,减少应用层的带宽压力。
容器里的上传文件为什么一重启就没了?
因为写在了容器可写层,容器重建即清空;需要挂持久卷,或者干脆写对象存储,日志和临时文件也建议分目录存放。
如果系统还在单机阶段,先把上传目录从代码目录里挪出来、单独做备份和磁盘告警,比急着上对象存储更划算;一旦实例数要变成两台以上,或者附件开始承担凭证角色,就按上面三档评估,优先把存储位置从某台机器换成一个独立的存储服务。要不要改、改到哪一档,取决于未来一年的扩容计划,而不是当下的文件大小。
-
上传目录跟着代码一起发版,图片全丢了,文件到底该存本地还是对象存储?
日期:2026年9月13日 阅读:184
-
客服帮用户重置了密码,用户说旧手机还能直接进,这算重置没成功吗?
日期:2026年11月11日 阅读:36
-
回滚时旧包连新库报字段不存在,直接拿备份把数据库退回去行不行?
日期:2026年11月10日 阅读:43
-
同一句查询早上几十毫秒、下午要好几秒,先查执行计划还是先查锁等待?
日期:2026年11月9日 阅读:36
-
客户下载的报表名字成了一串 %E4,我们办公室几台电脑都正常,这种只在一台机器冒出来的问题该从哪儿看?
日期:2026年11月7日 阅读:78




