|
用文件控件做填报,时间一长基本都会遇到两种对不上。
一、先说一个常见现象
情况 A:库里有记录,服务器上没文件
报表点开是空白的,或者点文件名下载报 404。
情况 B:服务器上有文件,库里没记录
磁盘一天天涨,但谁也说不清这些文件是谁传的、属于哪张单。
两种都很常见,而且官方没有现成的工具查。
二、为什么会这样
文件控件上传时,只做两件事:
- 把文件写到服务器某个目录
- 把文件名(或路径)写进你业务表的一个 varchar 字段
问题就出在"只有文件名"这一层:
- 同名文件会覆盖,后传的把前传的干掉
- 中文文件名在不同编码环境下会变成乱码,记录还在,文件找不到
- 报表里删掉一行数据,文件不会跟着删,就变成了残留
- 服务器迁移、换目录,记录里的路径就全废了
本质是:文件和记录之间没有强关联,也没有人负责回收。
三、怎么查(可以直接用)
思路:把"库里的清单"和"磁盘上的清单"各自导出来,做差集。
第 1 步:导出库里的清单
建一个数据集:
SELECT id, file_name, upload_time
FROM 你的业务表
WHERE file_name IS NOT NULL
在帆软里做个普通报表,导出 Excel。
第 2 步:导出磁盘上的清单
Windows:
dir /b /s D:\upload > files.txt
Linux:
find /opt/upload -type f > files.txt
第 3 步:对比
Excel 里用 VLOOKUP 也行,命令行更快:
# 只留文件名
awk -F/ '{print $NF}' files.txt | sort > disk.txt
sort db.txt | sort > db_sorted.txt
# 库里有、磁盘没有 → 丢的
comm -23 db_sorted.txt disk.txt
# 磁盘有、库没有 → 残留的
comm -13 db_sorted.txt disk.txt
跑完你会看到两个数字,通常都不小。
四、根治的思路(三条)
查只是止血,要不再复发得改设计。
① 文件名别用原名,用内容哈希
原名: 发票 2024年8月(1).jpg ← 中文、空格、括号、可能重名
存储名:a3f5c9...e21.jpg ← 纯哈希,不会重名、不会乱码
原名只存数据库,展示时还原。这一步能解决 80% 的"文件找不到"。
② 业务表只存附件 ID,不存文件名
-- 不要这样
attach_name varchar(255)
-- 这样
attach_ids varchar(255) -- 存 "1275,1276"
文件名、大小、上传人、时间、存储位置,全都放在附件表里。
这样附件才有"台账",才查得动。
③ 删除要能回收
- 业务删除 → 附件进回收站,不立刻删文件
- 回收站保留 N 天 → 到点才真删
- 定期扫孤儿文件 → 清掉没有记录的残留
没有这三步,磁盘只会一直涨。
五、最后
上面这套东西我整理成了一个插件:附件会自己建表、有台账、有回收站、能扫孤儿文件,支持存本地或对象存储。
商城搜「温靖附件中心」就能看到。
如果你只是想知道自己现在丢了多少文件,按第三节那三步跑一遍就够了,不用装任何东西。
|