gpt4 book ai didi

javascript - Chrome 扩展 : how to pass ArrayBuffer or Blob from content script to the background without losing its type?

转载 作者:可可西里 更新时间:2023-11-01 02:30:33 27 4
gpt4 key购买 nike

我有这个内容脚本,它使用 XHR 下载一些二进制数据,稍后发送到后台脚本:

var self = this;
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if (this.status == 200) {
self.data = {
data: xhr.response,
contentType: xhr.getResponseHeader('Content-Type')
};
}
};
xhr.send();

... later ...
sendResponse({data: self.data});

在后台脚本中收到此数据后,我想形成另一个 XHR 请求,将此二进制数据上传到我的服务器,所以我这样做:

var formData = new FormData();
var bb = new WebKitBlobBuilder();
bb.append(data.data);
formData.append("data", bb.getBlob(data.contentType));
var req = new XMLHttpRequest();
req.open("POST", serverUrl);
req.send(formData);

问题是上传到服务器的文件只包含这个字符串:“[object Object]”。我猜这是因为 ArrayBuffer 类型在从内容进程传输到后台时以某种方式丢失了?我该如何解决?

最佳答案

在内容脚本和后台页面之间传递的消息是 JSON 序列化的。

如果你想转移一个ArrayBuffer对象通过 JSON 序列化 channel ,在传输之前和之后将缓冲区包装在 View 中。

我展示了一个孤立的例子,因此解决方案是普遍适用的,而不仅仅是你的情况。该示例显示了如何传递 ArrayBuffer s 和类型化数组,但该方法也可以应用于 FileBlob对象,通过使用 FileReader API。

// In your case: self.data = { data: new Uint8Array(xhr.response), ...
// Generic example:
var example = new ArrayBuffer(10);
var data = {
// Create a view
data: Array.apply(null, new Uint8Array(example)),
contentType: 'x-an-example'
};

// Transport over a JSON-serialized channel. In your case: sendResponse
var transportData = JSON.stringify(data);
//"{"data":[0,0,0,0,0,0,0,0,0,0],"contentType":"x-an-example"}"

// At the receivers end. In your case: chrome.extension.onRequest
var receivedData = JSON.parse(transportData);

// data.data is an Object, NOT an ArrayBuffer or Uint8Array
receivedData.data = new Uint8Array(receivedData.data).buffer;
// Now, receivedData is the expected ArrayBuffer object

此解决方案已在 Chrome 18 和 Firefox 中成功测试。

  • new Uint8Array(xhr.response) 用于创建 ArrayBuffer 的 View , 以便可以读取各个字节。
  • Array.apply(null, <Uint8Array>) 用于创建一个普通数组,使用来自 Uint8Array 的键看法。此步骤减小了序列化消息的大小。 警告:此方法仅适用于少量数据。当类型数组的大小超过 125836 时,将抛出 RangeError。如果您需要处理大量数据,请使用其他方法在类型化数组和普通数组之间进行转换。

  • 在接收端,原始缓冲区可以通过creating a new Uint8Array 获得,并阅读 buffer attribute .

在您的 Google Chrome 扩展程序中实现:

// Part of the Content script
self.data = {
data: Array.apply(null, new Uint8Array(xhr.response)),
contentType: xhr.getResponseHeader('Content-Type')
};
...
sendResponse({data: self.data});

// Part of the background page
chrome.runtime.onMessage.addListener(function(data, sender, callback) {
...
data.data = new Uint8Array(data.data).buffer;

文档

关于javascript - Chrome 扩展 : how to pass ArrayBuffer or Blob from content script to the background without losing its type?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8593896/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com