批量上传图片只传了一张怎么办,同名文件被覆盖了

alt:三个同名文件字段进服务器,只剩最后一个,前端却提示全部成功
alt:三个同名文件字段进服务器,只剩最后一个,前端却提示全部成功

批量上传图片只传了一张 —— 那天我一次选了 3 张,编辑器弹「上传成功」,接口也返回成功。可服务器那边只躺着 1 张,存的也只有最后那一张。

批量上传只传一张,我先怀疑了前端

「上传成功」这四个字是前端给的,依据只有 HTTP 状态码和响应里的 success 字段。文件到底落了几张,界面上不显示。

我以为问题在编辑器身上。它有个张数上限,我先去翻那个配置。

uploadImgMaxLength,默认值 1e4。

一万张。不是它。

文件选择框也带 multiple,多选功能是有的。前端一个都没拦。

翻源码才看见那一行

问题在发请求的那段。wangEditor 3.1.1 源码里是这么写的:

b.append(d || e.name, e)

d 是配置里的 uploadFileName,e 是选中的那个文件。三个文件、三次 append,用的是同一个字段名。表单里于是出现三个同名项。

PHP 收到同名文件字段不报错。它默默把后一个盖掉前一个。

$_FILES['file'] 里最后只剩一张,结构也是单张的结构,不是数组。

这也是「接口返回成功、实际没生效」那一类。判断有没有真生效,得看对面回了什么,不能看自己的提示框 —— 我在百度推送那个坑上吃过一次亏。

改一个字符

PHP 对带方括号的字段名会自己转成数组。模板里那个 uploadFileName 改成 'file[]' 就够了:

uploadFileName: 'file[]'

后端得跟着改,因为接到的结构变了。加一个判断分支走多文件,单文件那条路一点没动:

if (is_array($_FILES['file']['tmp_name'])) {
    // 多文件:逐个走单张的保存逻辑
}

单张的保存逻辑我抽成一个私有方法,多文件的循环体里直接调它。

后缀白名单校验、保存、压缩,一处都不重写。

alt:左边字段名不带方括号被后一个覆盖,右边带方括号变成数组,三张全收
alt:左边字段名不带方括号被后一个覆盖,右边带方括号变成数组,三张全收

兼容性差点翻车

改完我顺手测了老的单图入口。那个上传接口不止编辑器在用,站里好几个地方的封面、头像、客服码走的都是它,字段名还是老的 file。

新的返回是数组 fileurls,老的返回是字符串 fileurl。老入口拿到数组,前端 insertImg(url) 会把数组转成字符串塞进 src,图直接裂。

所以返回改成两个都给。多图给 fileurls 数组,同时保留 fileurl 放第一张。老代码读 fileurl 拿到的还是第一张,行为不变。

限张我也顺手设成 9。PHP 那边有 max_file_uploads 的默认上限,前端多放点总比撞墙强。

验证

改完我拿服务器上的模板源码直接 grep 一遍。这步是踩过坑的 —— ssh 里套多层引号跑 grep,正则被转义吃掉,读出来一个 0,我以为改动没落盘。改成在本地 grep 模板源文件才对上:

grep -rn "uploadFileName" template/ | grep "file\[\]"
grep -rn "is_array" application/ | grep "_FILES"
ls backup/ | grep editor_filename

改 PHP 文件上生产站我另外写了套安全网,备份、语法检查、dry-run 都过一遍才敢动。这次一改就是 10 个模板乘两个站,而且两个站的模板文件 md5 完全一样,漏改一处就一边好一边坏。

实测下来,单张还是老的返回格式,3 张返回 3 个元素的 fileurls。

具体是哪 10 个模板我当时没逐个记下来,只记得是两站各一半,全是编辑器的。

3 张进,3 张出。

发表评论