日期: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 年就封死了。
GetForegroundWindow() 返回 0,键盘输入无处落地。真正能穿过 isTrusted 防线的只有「操作系统级的真实输入」,而真实输入的前提是窗口有焦点。方案没有全废:对话框能被真实拉起(这一步已验证通过),把整条链封装成 tools/ks_upload_oneclick.py——下次会话有前台焦点时,一次执行即可跑通。也即:技术路线本身没错,只是执行时机错了,等一个有焦点的窗口。
带走的结论:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。