multiple属性无法自动降级,必须通过change事件中检测input.files.length>1来判断真实多选能力,旧ios safari(16.4前)强制单选且静默忽略,需改用多次单选或引导换环境。

multiple 属性本身无法降级,只能检测后换方案
HTML 的 multiple 属性不是开关式功能,它没有“关闭后自动退化为单选”的行为。加了它,浏览器要么支持多选(返回 input.files.length > 1),要么静默忽略(如旧版 iOS Safari,files.length 永远是 1)。你不能靠它触发 fallback,必须主动检测环境并切换逻辑。
关键判断点不是“有没有 multiple”,而是“用户是否真能选多个文件”:
- 用
input.files.length > 1在change事件里实测——这是唯一可信依据 - 避免依赖
navigator.userAgent做硬编码判断,iOS 版本号、微信 WebView 行为都可能突变 - 对 Android 微信等场景,即使写了
multiple,也要在 change 后立刻检查长度,别假设它一定生效
旧 iOS Safari(16.4 之前)必须放弃原生 multiple
iOS Safari 在 16.4 之前版本中,<input type="file" multiple> 会强制降级为单选,且不报错、不提示、不触发任何警告。用户点了十次,input.files 里永远只有最后一个文件。
可行的应对方式只有两种:
- 改用多次单选:隐藏原生 input,每次点击“添加文件”按钮时动态创建一个新
<input type="file">,把选中的File推入自维护的files = []数组 - 引导用户换环境:检测到旧 iOS 后,在 UI 上显示轻量提示,例如「请使用 Safari 桌面版或 Chrome」,而不是强行做复杂模拟
- 别试图用 JS 触发 click 多次——移动端 input 不允许脚本自动调起文件选择器,会直接被拦截
select[multiple] 在移动端根本不能用
原生 <select multiple></select> 在 iOS Safari 中会被完全绕过:点击后弹出的是单选式全屏 Picker,不显示已选项,无法反选,selectedOptions 始终只返回一个。这不是 bug,是 WebKit 主动限制。
如果你需要真多选,必须放弃 select:
- 用
<div role="listbox" aria-multiselectable="true"> + 手动管理 <code>aria-selected和焦点逻辑 - 或者直接上轻量级 JS 库(如 choices.js),但得确保它内部不依赖原生
select的 multiple 行为 - 千万别在
change事件里读select.value——它永远只返回第一个值,正确写法是Array.from(select.selectedOptions).map(opt => opt.value) - PHP:必须用
$_FILES['files']['name'](数组),不能用$_FILES['files']['name'][0]假设单值 - Node.js(Express + multer):需配置
multer().array('files')或multer().fields([{ name: 'files', maxCount: 10 }]) - fetch + FormData:用
formData.getAll('files')拿全部,get()只返回第一个 - 别在后端拼接字符串再 split —— 文件名含逗号、空格、中文时会崩
表单提交时 name 重复发送,后端不接住就丢文件
前端无论有没有 multiple,表单提交时字段名都一样;区别在于:有 multiple 时,同名字段会以重复参数形式发送,例如 files=a.jpg&files=b.png&files=c.pdf。
后端如果没按数组处理,就会只收到第一个:
最易被忽略的一点:你前端验证了 iOS 降级、做了多次单选收集、也传了多个文件,但后端只取第一个,等于白忙活。兼容性问题从来不只是前端的事。











