news 2026/9/7 1:47:54

Electron 中 UploadData 对象详解:请求上传体的结构定义、API 使用与源码实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Electron 中 UploadData 对象详解:请求上传体的结构定义、API 使用与源码实现

Electron 中 UploadData 对象详解:请求上传体的结构定义、API 使用与源码实现

【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron

Electron 的UploadData对象是网络栈向 JS 层暴露"正在上传的请求体"的标准数据结构,主要出现在webRequest事件细节与协议处理相关的结构中。读懂它的三个字段、弄清楚它在session.webRequest监听器中的出现位置,并对照 源码转换器 了解 Chromium 底层四种上传元素是如何映射成 JS 对象的,你就能在拦截请求时准确识别普通字节、磁盘文件、Blob 和流式上传这四类载荷。

UploadData 对象:官方定义与字段语义

UploadData 官方结构定义 非常紧凑,全文只有三个字段,这里完整继承并展开说明:

字段类型是否可选说明
bytesBuffer必填正在发送的内容(Content being sent)
filestring可选正在上传的文件路径(Path of file being uploaded)
blobUUIDstring可选Blob 数据的 UUID,配合 ses.getBlobData 方法取回实际数据

三个字段分别对应三种典型的上传场景:

  • bytes:请求体在内存中、可以直接以Buffer形式读取时(例如fetch上传字符串/ArrayBuffer),转换器会把底层字节复制成 JS Buffer 挂到该字段上;
  • file:上传的是一段磁盘文件(例如multipart/form-data中通过Filefs路径构造的部分)时,JS 层拿到的只是文件路径字符串,文件内容并不会被整体拷贝进内存;
  • blobUUID:上传数据来自 Blob(DataPipe 形式)时,对象上只携带一个 UUID 标识符,需要通过session实例的ses.getBlobData(identifier)方法按标识取回数据——这一点在官方文档中作为blobUUID字段的说明被明确写出。

UploadData 出现的位置

webRequest 事件中的details.uploadData

WebRequest 模块文档 中,uploadDataUploadData[]数组形式出现在两个监听器的details对象里:

  1. webRequest.onBeforeRequest([filter, ]listener)details.uploadData[UploadData[]](docs/api/structures/upload-data.md)(非可选),文档原文明确写道 "The uploadDatais an array ofUploadDataobjects"。该事件在请求即将发出时触发,监听器必须通过callback返回一个含cancelredirectURL等可选字段的 response 对象。
  2. webRequest.onBeforeSendHeaders([filter, ]listener)details.uploadData[UploadData[]](docs/api/structures/upload-data.md)(可选,因为并非所有请求都带上传体),此时details中还会附带requestHeaders,适合在发头阶段检查上传内容并改写请求头。

两个监听器都支持通过WebRequestFilter按 URL 过滤,文档给出的合法 URL 模式 包括:

'<all_urls>' 'http://foo:1234/' 'http://foo.com/' '*://*/*' '*://example.com/*' 'http://*.foo:1234/' 'file://foo:1234/bar'

ProtocolRequest 结构中的可选uploadData

ProtocolRequest 结构 定义了描述一次请求的对象:urlreferrermethodheaders,以及可选的uploadData字段,其类型同样是UploadData[]。也就是说,在协议处理的请求描述中,上传体同样以 UploadData 数组的形式暴露给嵌入方。

源码实现:Chromium 上传数据如何变成 UploadData

从源码结构看,UploadData并不是 Electron 自己构造的数据,而是 Chromium 网络栈请求体对象的 JS 投影。关键转换逻辑位于 Converternetwork::ResourceRequestBody::ToV8:它遍历底层network::ResourceRequestBodyelements(),按DataElement::Tag枚举逐一分发,构造出 JS 对象数组。四种底层元素到 JS 字段的映射关系如下(见 net_converter.cc):

底层 mojom 元素type字段写入的 JS 属性
kFileDataElementFilefilefilefilePathoffsetlengthmodificationTime
kBytesDataElementBytesrawDatabytes(通过electron::Buffer::Copy拷贝字节)
kDataPipe(Blob)blobblobUUIDdataPipe
kChunkedDataPipe(流)streambodyReadableStream包装)

可以推断出几个文档未展开、但源码中明确存在的事实:

  1. 文档字段是"简化视图"。官方结构文档只列了bytes/file/blobUUID三个字段,而转换器实际还会写入type以及文件元素的filePathoffsetlengthmodificationTimetype字段(取值file/rawData/blob/stream)可以看作区分四种载荷的判断依据。
  2. 字节拷贝发生在转换时kBytes分支调用electron::Buffer::Copy,意味着bytesBuffer 是底层数据的一份副本;而kFile分支只传递路径,不触发内容读取,对大文件上传的拦截检查(只读路径、校验文件名等)是零拷贝的。
  3. Blob 的数据管道生命周期绑定在 UploadData 对象上。源码注释写道 "The lifetime of data pipe is bound to the uploadData object",即dataPipe属性(DataPipeHolder)与uploadData对象同生命周期——如果你要异步处理 Blob 数据,需要保证持有该uploadData对象或及时用getBlobData取回内容。
  4. getBlobData有被重构的意图。源码中的 TODO 注释 表明:在 NetworkService 重构之后,旧的blobUUIDAPI 变得"不必要地复杂",未来计划弃用getBlobData并直接返回DataPipeHolder包装器。因此在使用blobUUID时宜将其视为稳定的当前 API,但不必为它设计过度复杂的持久化方案。

通过 getBlobData 取回 Blob 内容

对携带blobUUID的 UploadData,官方文档给出的取数方式是ses.getBlobData(identifier),其定义位于 Session API 文档。典型的使用链路是:webRequest监听器拿到details.uploadData中某个元素的blobUUID→ 调用对应sessiongetBlobData→ 按 UUID 换回 Blob 数据。对于file元素,则直接根据file路径用fsAPI 处理即可。

与相近结构的区分

仓库中还有几个容易与UploadData混淆的结构,注意它们的适用场景不同:

  • UploadRawData / UploadFile{type: 'rawData', bytes}{type: 'file', filePath, offset, length, modificationTime}两种结构,是 PostBody 对象 中data数组的元素类型。PostBody(含contentTypeboundarycontentType只允许application/x-www-form-urlencodedmultipart/form-data,对应 HTML 表单的enctype)用于表单提交场景,与UploadData的网络栈来源是两条不同的暴露路径;
  • ProtocolResponseUploadData:只有contentType(MIME 类型)与data(string | Buffer)两个字段,出现在 ProtocolResponse 中,属于协议处理器侧的上传响应数据,与请求拦截侧的UploadData不是一回事。

实战示例:在 webRequest 中检查上传内容

结合上述结构定义,一个合法的拦截检查逻辑如下(字段取值与 UploadData 定义、webRequest 事件细节 完全对应):

const { session } = require('electron') const ses = session.defaultSession ses.webRequest.onBeforeRequest( { urls: ['*://*/*'] }, (details, callback) => { for (const chunk of details.uploadData) { if (chunk.file) { // 磁盘文件上传:只拿到路径,按需再读文件 console.log('file upload:', chunk.file) } else if (chunk.blobUUID) { // Blob 上传:用 UUID 异步取回数据 ses.getBlobData(chunk.blobUUID).then(data => { console.log('blob data size:', data.length) }) } else if (chunk.bytes) { // 内存中的原始字节 console.log('raw bytes:', chunk.bytes.length) } } callback({}) } )

注意:onBeforeRequestuploadData是必填字段,而onBeforeSendHeaders中它是可选的,后者使用时应先做空值判断。

小结

  • UploadDatabytes(Buffer,必填)、file(string,可选)、blobUUID(string,可选)三字段组成,分别覆盖内存字节、磁盘文件、Blob 三类上传内容;
  • 它主要出现在webRequestonBeforeRequest/onBeforeSendHeaders细节与ProtocolRequest结构中,以数组形式暴露;
  • 从源码看,它由 net_converter.cc 将 Chromium 的ResourceRequestBody四种DataElement(file / rawData / blob / stream)转换而来,实际对象上还带有type等文档未列出的字段;
  • 取回 Blob 数据使用ses.getBlobData(identifier);与PostBodyProtocolResponseUploadData等相似结构应明确区分场景后再使用。

【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 1:46:01

本地部署代码大模型:Ollama一键运行Qwen与DeepSeek

先给出结论&#xff1a;2026年再聊开源代码大模型本地部署&#xff0c;已经不是那种“折腾半天连个环境都配不明白”的事。Qwen2.5-Coder和DeepSeek Coder这两个系列&#xff0c;如今只要一台带NVIDIA显卡的普通电脑&#xff0c;哪怕是8GB显存&#xff0c;都能用一条命令把模型…

作者头像 李华
网站建设 2026/9/7 1:44:08

大模型“纯血自研”真假难辨?从Tokenizer到API行为四步识别套壳模型

这两天行业群被一个消息炸得不轻&#xff1a;中东那边冒出一个号称“纯血自研”的大模型&#xff0c;发布会PPT写得相当有排面&#xff0c;从芯片到框架到训练框架全是我方掌控的气势。结果没热闹两天&#xff0c;就有技术老哥扒出这模型的推理风格、返回结构和语料习惯跟MiniM…

作者头像 李华
网站建设 2026/9/7 1:44:04

人形机器人强化学习导航真机部署:以众擎PM01为例

这次我们来看一个非常具体、也比较硬核的方向&#xff1a;众擎 PM01 人形机器人的强化学习导航真机部署。如果你是做机器人导航、强化学习策略迁移或者 ROS2 真机部署的工程师&#xff0c;这篇文章可以直接收藏。重点不是把强化学习算法再讲一遍&#xff0c;而是把“仿真里训练…

作者头像 李华