Skip to content

浏览器自动化里的文件上传注入实践

更新: 1970/1/1 字数: 0 字 时长: 0 分钟

最近在做一个表单自动化项目,最容易踩坑的环节其实不是输入框,而是上传图片。
看起来“点上传按钮 -> 打开文件管理器 -> 选文件”很直觉,但自动化里这条路反而最不稳定。

这篇记录我最终采用的方法:不操作系统文件管理器,直接把文件注入到 input[type=file]


为什么不走文件管理器

文件管理器属于操作系统层,不同浏览器、不同系统主题、不同权限策略下都可能变化。
自动化脚本最怕的就是“环境依赖太重”。

网页里的 input[type=file] 才是上传的真实入口。
只要能定位到它,就能稳定注入文件列表。


核心思路

  1. 先定位上传区域,不要用全局“上传图片”按钮。
  2. 在该区域内寻找 input[type=file]
  3. 通过 fetch -> Blob -> File -> DataTransfer 组装文件。
  4. DataTransfer.files 赋给 input.files
  5. 触发 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]

我在项目里做了四层兜底:

  1. 当前节点子树内找 input[type=file]
  2. 当前行容器内找(避免串到别的上传区)
  3. 向上逐层祖先兜底
  4. 在最近上传容器内兜底

并且优先 accept 包含 image 的 input,避免命中“上传视频”。


配置层建议

上传类字段不要用宽泛 selector(如 button.pm-button-upload)。
应绑定到业务区块,例如:

yaml
selector: "div[data-auto-test-id*='exteriorPicUrlList'] .next-upload-inner"

这样即使页面上有多个“上传图片”按钮,也能锁定到“车辆外观图片”这一块。


我踩过的坑

  1. 选择器太泛,命中上方“上传视频”。
  2. 只点按钮,不找真实 input[type=file]
  3. 文件注入后没触发事件,页面无感知。
  4. 字段名编码异常,导致映射项被跳过。

调试清单

  1. 先打印命中的 selector。
  2. 打印命中的 input 的 name/accept/multiple
  3. 注入前后检查 input.files.length
  4. 检查页面缩略图数量是否变化。

结论

自动化上传的稳定性,核心不在“点击按钮”,而在“精准找到 input 并注入文件”。
把上传流程从系统文件管理器剥离后,跨环境稳定性会提升一个量级。

本站访客数 人次 本站总访问量