浏览器自动化里的文件上传注入实践
更新: 1970/1/1 字数: 0 字 时长: 0 分钟
最近在做一个表单自动化项目,最容易踩坑的环节其实不是输入框,而是上传图片。
看起来“点上传按钮 -> 打开文件管理器 -> 选文件”很直觉,但自动化里这条路反而最不稳定。
这篇记录我最终采用的方法:不操作系统文件管理器,直接把文件注入到 input[type=file]。
为什么不走文件管理器
文件管理器属于操作系统层,不同浏览器、不同系统主题、不同权限策略下都可能变化。
自动化脚本最怕的就是“环境依赖太重”。
网页里的 input[type=file] 才是上传的真实入口。
只要能定位到它,就能稳定注入文件列表。
核心思路
- 先定位上传区域,不要用全局“上传图片”按钮。
- 在该区域内寻找
input[type=file]。 - 通过
fetch -> Blob -> File -> DataTransfer组装文件。 - 把
DataTransfer.files赋给input.files。 - 触发
input/change事件,让页面感知上传。
关键实现
1) 上传文件注入
js
async function uploadFiles(inputEl, files) {
if (!files?.length) return;
const dt = new DataTransfer();
for (const f of files) {
const resp = await fetch(f.url);
if (!resp.ok) throw new Error(`Fetch file failed: ${resp.status} ${f.url}`);
const blob = await resp.blob();
const fileObj = new File([blob], f.name || "upload.bin", {
type: blob.type || "application/octet-stream"
});
dt.items.add(fileObj);
}
inputEl.files = dt.files;
inputEl.dispatchEvent(new Event("input", { bubbles: true }));
inputEl.dispatchEvent(new Event("change", { bubbles: true }));
}2) 精准选择 input[type=file]
我在项目里做了四层兜底:
- 当前节点子树内找
input[type=file] - 当前行容器内找(避免串到别的上传区)
- 向上逐层祖先兜底
- 在最近上传容器内兜底
并且优先 accept 包含 image 的 input,避免命中“上传视频”。
配置层建议
上传类字段不要用宽泛 selector(如 button.pm-button-upload)。
应绑定到业务区块,例如:
yaml
selector: "div[data-auto-test-id*='exteriorPicUrlList'] .next-upload-inner"这样即使页面上有多个“上传图片”按钮,也能锁定到“车辆外观图片”这一块。
我踩过的坑
- 选择器太泛,命中上方“上传视频”。
- 只点按钮,不找真实
input[type=file]。 - 文件注入后没触发事件,页面无感知。
- 字段名编码异常,导致映射项被跳过。
调试清单
- 先打印命中的 selector。
- 打印命中的 input 的
name/accept/multiple。 - 注入前后检查
input.files.length。 - 检查页面缩略图数量是否变化。
结论
自动化上传的稳定性,核心不在“点击按钮”,而在“精准找到 input 并注入文件”。
把上传流程从系统文件管理器剥离后,跨环境稳定性会提升一个量级。