浏览器插件框架中运行js并上传文件简化过程

动作开发 · 967 次浏览
涛涛涛 创建于 2天6小时前

async function 运行js代码并上传文件(e) {
            let { tabId: t, jsdm: h ,files:g } = e;
            var n={tabId: t};
            let a= await chrome.debugger.attach(n, "1.3");
            a= await chrome.debugger.sendCommand(n, "Runtime.evaluate", {expression: h});//运行js代码并返回objectId
            let objectId=a.result.objectId;   //获取元素文件框的objectId
            await chrome.debugger.sendCommand(n, "DOM.setFileInputFiles", { objectId:objectId, files: g})       //上传文件路径
}

js代码格式如下:
var gg=window.frames[1];                            //切换到指定框架,从顶层框架里查找frames的位置,并切换到frame框架里面
gg.document.querySelector('#textInput').value=123;       //指定框架运行的js代码
gg.aa=[1,2,3,4,5];                                             //向框架中声明全局变量aa
gg.document.querySelector('#fileInput');    //获取框架中元素文件框的objectId一定要放到最后一行,为上传文件准备

最后一行一定要为文件框元素,例如:gg.document.querySelector('#fileInput'),这样就可以获取到获取元素文件框的objectId,不要写属性

注意:使用Runtime.evaluate直接在js代码上切换到指定框架【window.frames[1]】,获取框架中元素文件框的objectId【gg.document.querySelector('#fileInput'); 】 这一步很关键!!!

//参数说明
tabId:  调试目标
jsdm: js代码
files:  需要上传文件的路径数组


//参数示例
{
tabId:  779853286,
jsdm: `var gg=window.frames[1];
          gg.document.querySelector('#textInput').value=123;
          gg.aa=[1,5,9,833,5];
          gg.document.querySelector('#fileInput');`,
files: ["C:/Users/Administrator/Desktop/11.png"]
}

注意:mv3版本地的网页可能不能使用(file:///开头的,可能是本地域不同造成的,Runtime.evaluate里面的限制)

以下是两个子程序可以测试:

https://getquicker.net/subprogram?id=3aa0bc73-e66b-48a7-8c78-08dda3deac8a(mv3版)

https://getquicker.net/subprogram?id=e60c459d-62a0-4792-8c88-08dda3deac8a(mv2版)

可以先用js声明一个函数,再指定是哪一个 iframe框架,再调用 如下:

function 指定框架(e) {
          let g= window.frames[e];
          g.document.querySelector('#textInput').value=123;
          g.aa=[1,5,9,833,5];
          let d=g.document.querySelector('#fileInput');
          return d
}

原理顺序:

一.连接tabId
chrome.debugger.attach({ tabId: tabId }, '1.3', () => {console.log('连接');})

二.Runtime.evaluate 运行js代码并获取元素文件框的objectId,为上传文件准备
chrome.debugger.sendCommand(
{ tabId: tabId }, 'Runtime.evaluate', {expression: 
`var gg=window.frames[1];
 gg.document.querySelector('#textInput').value=123;
 gg.aa=[1,2,3,5,4];
 gg.document.querySelector('#fileInput');`
}, function(response) {console.log(response.result.objectId);});

result格式如下:
{
    "className": "HTMLInputElement",
    "description": "input#fileInput",
    "objectId": "-2475387284660854303.1.1",
    "subtype": "node",
    "type": "object"
}

三.DOM.setFileInputFiles 上传文件路径
chrome.debugger.sendCommand({tabId: tabId}, "DOM.setFileInputFiles", {"objectId": "-2475387284660854303.1.1","files":["C:/Users/Administrator/Desktop/11.png"]})

 

下面是一些原理过程,可以相互推导,目的不同,需要用的数据不同

目的是为了获取iframe框架的上下文ID  转了一圈,可以相互推导求值  iframe框架上下文ID是变化的,网页刷新、表单提交等 iframe框架上下文ID也会跟着变化

1.Runtime.evaluate  这是顶层框架    顶层框架上下文ID,也就是默认的,可以省略,理论上开始的上下文ID,默认是1 网页刷新、表单提交等上下文ID会跟着变化
chrome.debugger.sendCommand({ tabId: tabId }, 'Runtime.evaluate', {expression: 
`var gg=window.frames[1];
 gg.document.querySelector('#textInput').value=123;
 gg.aa=[1,2,3,5,4];
 gg.document.querySelector('#fileInput');`}, function(response) {console.log( response.result.objectId );});
result格式如下:
{
    "className": "HTMLInputElement",
    "description": "input#fileInput",
    "objectId": "4489587955195509192.14.8",     //  顶层框架上下文ID【14】,也就是默认的,可以省略
    "subtype": "node",
    "type": "object"
}


2.DOM.describeNode 获取iframe框架的backendNodeId
chrome.debugger.sendCommand({tabId: tabId}, 'DOM.describeNode',{ objectId :'4489587955195509192.14.8' },(result) => {console.log( result.node.backendNodeId );})
node格式如下:
{
    "attributes": [
        "type",
        "file",
        "id",
        "fileInput",
        "name",
        "fileInput"
    ],
    "backendNodeId": 1112,
    "childNodeCount": 0,
    "localName": "input",
    "nodeId": 0,
    "nodeName": "INPUT",
    "nodeType": 1,
    "nodeValue": "",
    "shadowRoots": [
        {
            "backendNodeId": 1116,
            "childNodeCount": 2,
            "localName": "",
            "nodeId": 0,
            "nodeName": "#document-fragment",
            "nodeType": 11,
            "nodeValue": "",
            "shadowRootType": "user-agent"
        }
    ]
}

3.DOM.resolveNode 获取iframe框架的objectId
chrome.debugger.sendCommand({tabId: tabId}, 'DOM.resolveNode',{ backendNodeId:1112 },(result) => {console.log( result.object.objectId );})
object格式如下:
{
    "className": "HTMLInputElement",
    "description": "input#fileInput",
    "objectId": "4489587955195509192.46.1",    iframe框架上下文ID【46】
    "subtype": "node",
    "type": "object"
}

4.Runtime.evaluate 通过iframe框架的上下文ID,运行js代码
chrome.debugger.sendCommand({tabId: tabId}, 'Runtime.evaluate', {expression:'var ss=[1,2,3,4];',contextId : 46 })

 

涛涛涛 最后更新于 2025/6/5

乐昂岚【接定制】 2天3小时前 :

强烈建议来这里发一遍 https://getquicker.net/KC/Kb/New

涛涛涛 回复 乐昂岚【接定制】 2天1小时前 :

嗯嗯,这样东西有些乱,它们互相关联,需要一个明确的目的,才能将其串联起来,单独来发,不知道怎样发

回复内容
DaveBoy 1天6小时前
#1

v2、v3都支持么

涛涛涛 回复 DaveBoy 1天5小时前 :

应该是都可以的,测试是都可以的

涛涛涛 回复 DaveBoy 1天4小时前 :

写了两个子程序可以试试看

回复主贴