首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >WorkBuddy 实战:无头浏览器里传一个视频文件,为什么 7 种方案全败

WorkBuddy 实战:无头浏览器里传一个视频文件,为什么 7 种方案全败

原创
作者头像
用户12800671
发布于 2026-10-24 10:45:18
发布于 2026-10-24 10:45:18
490
举报

日期:2026-10-24。任务是让自动化账号往快手创作中心传一条竖版视频。浏览器自动化点按钮、填表单都熟了,卡了一个下午的居然是「把本地文件塞进上传框」这一步。把 7 种尝试和最终根因记下来,给所有做无人值守发布流水线的人省时间。

场景约束

会话是 CDP 远程调试连上去的 Edge,无头模式,宿主机上没有前台窗口焦点。上传入口是平台自家的文件选择对话框。这三个条件凑齐,就是下面 7 连败的土壤。

七种方案,逐一验尸

1. CDP DOM.setFileInputFiles**。** 教科书做法:拿到 <input type=file> 的 backendNodeId,直接把文件路径塞进去。实测返回成功,但读回 input.files.length 永远是 0。原因:页面用了自定义上传组件,真实 input 不在文档流里挂载,节点拿到了也白拿。

2. Page.setInterceptFileChooserDialog + backendNodeId。 拦截文件选择器再注入路径。结果同样是 files=0——拦截到的对话框归属的 input,和 1 是同一个,根子相同。

3. 合成 DataTransfer + change 事件。 在页面里 new DataTransfer(),手工往 items.add(file),再赋给 input.files,最后派发 change。JS 层看着一切正常,页面回调却不触发。平台的防护逻辑在核对事件的 isTrusted——脚本合成的事件永远是 false,直接被丢弃。

4. 合成 drop 事件。 把 File 对象包进 drag 事件丢给上传区。同一条防线:isTrusted=false,页面不认。

5. base64 内嵌。 干脆不用文件系统:把视频读成 base64,在页面里 atob 还原成 Blob。问题是页面根本没有「从内存创建素材」的注入面,上传必须走它的对话框,此路从入口就不存在。

6. fetch 隧道。 本机起一个 HTTP 服务让页面去 fetch 本地文件再转 Blob。实测掉进代理黑洞:页面环境挂着系统代理,本机地址被路由进代理 tunnels 后无响应。要绕就得改浏览器代理白名单,牵连整个登录态,不值得。

7. Win32 WM_SETTEXT**。** 对话框弹出后,用窗口消息往文件名输入框写字。Vista 以后的系统文件对话框是假 Edit 控件,WM_SETTEXT 收得到字符却不进内部状态,回车后路径为空。这条老路 2010 年就封死了。

根因只有两条

  1. 平台 isTrusted 防护:所有脚本合成的事件一律不被信任,第 3、4 种方案死在这。
  2. 断连会话无前台焦点:GetForegroundWindow() 返回 0,键盘输入无处落地。真正能穿过 isTrusted 防线的只有「操作系统级的真实输入」,而真实输入的前提是窗口有焦点。

沉淀与结论

方案没有全废:对话框能被真实拉起(这一步已验证通过),把整条链封装成 tools/ks_upload_oneclick.py——下次会话有前台焦点时,一次执行即可跑通。也即:技术路线本身没错,只是执行时机错了,等一个有焦点的窗口。

带走的结论:

  1. 文件上传是浏览器自动化里单独的一类难题,和点击、填表不是一个难度级别,排期时要单独留时间。
  2. 判断页面认不认合成事件,先测一次 isTrusted,省掉 3、4 那类无效功。
  3. 无人值守和「需要真实输入」天然冲突:上传这类动作优先安排在有前台焦点的会话窗口执行,而不是在无头会话里硬凿 7 种歪路。先确认执行环境支持什么,再选技术路线,顺序反了就是一个下午的 7 连败。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 场景约束
  • 七种方案,逐一验尸
  • 根因只有两条
  • 沉淀与结论
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档