I have this content script that downloads some binary data using XHR, which is sent later to the background script:
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});
After receiving this data in background script, I’d like to form another XHR request that uploads this binary data to my server, so I do:
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);
The problem is that the file uploaded to the server contains just this string: “[object Object]”. I guess this happens because ArrayBuffer type is lost somehow while transferring it from content process to the background? How can I solve that?
Messages passed between a Content Script and a background page are JSON-serialized.
If you want to transfer an
ArrayBufferobject through a JSON-serialized channel, wrap the buffer in a view, before and after transferring.I show an isolated example, so that the solution is generally applicable, and not just in your case. The example shows how to pass around
ArrayBuffers and typed arrays, but the method can also be applied toFileandBlobobjects, by using theFileReaderAPI.This solution has been tested successfully in Chrome 18 and Firefox.
new Uint8Array(xhr.response)is used to create a view of theArrayBuffer, so that the individual bytes can be read.Array.apply(null, <Uint8Array>)is used to create a plain array, using the keys from theUint8Arrayview. This step reduces the size of the serialized message. WARNING: This method only works for small amounts of data. When the size of the typed array exceeds 125836, a RangeError will be thrown. If you need to handle large pieces of data, use other methods to do the conversion between typed arrays and plain arrays.At the receivers end, the original buffer can be obtained by creating a new
Uint8Array, and reading thebufferattribute.Implementation in your Google Chrome extension:
Documentation
ArrayBufferUint8Array<Function> .apply“This lets you send a one-time JSON-serializable message from a content script to extension, or vice versa, respectively”