须知
谷歌扩展只能传输和JSON兼容的数据,可通过JSON.parse(JSON.stringify(form_data))判断兼容与否。
解决方案
FormData和JSON不兼容。要上传文件,可通过发送方将File对象转换为dataURL,接收方解析回File对象,再生成FormData对象上传文件。本地应用和插件通信是通过Chrome.runtime.sendMessage和Chrome.runtime.onMessageExternal。详细过程如下:
代码
发送方:本地应用
let fileReader = new FileReader();
fileReader.onload = function(evt) {
const dataURL = evt.target.result;
// 本地应用发送数据
chrome.runtime.sendMessage(extId, {
method: 'POST', // 这里由于插件,我用的是fetch。ajax用type
dataURL,
url,
headers
}, (res) => {
if (res.status === 0) {
resolve(res);
} else {
reject(res);
}
});
}
// 将本地获取的file对象转换为dataURL
fileReader.readAsDataURL(file);
接收方:谷歌插件
chrome.runtime.onMessageExternal.addListener((message, sender, sendResponse) => {
const { dataURL, url, ...rest } = message,
blob = dataURLtoBlob(dataURL),
img = blobToFile(blob, 'img'),
formData = new FormData();
formData.append('upload', img);
rest.body = formData; // fetch格式
// 上传给服务器
fetch(url, rest)
.then(res => res.json()) // fetch需要使用res.json()才能获取到数据
.then((res) => {
if (res.message === 'success') {
sendResponse({ status: 0, res });
} else {
sendResponse({ status: -1, res });
}
});
}
接收方:格式转换代码
// dataURL转换为Blob
const dataURLtoBlob = (dataUrl) => {
let arr = dataUrl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime
})
}
// Blob转换为File
const blobToFile = (blob, fileName) => {
return new File([blob], fileName);
}
其他方案:
SharedWorker
相关文章:
File对象、dataURL、Blob对象互转
Message Passing - Google Chrome
chrome.runtime.onMessageExternal - Google Chrome
javascript - Does chrome.runtime support posting messages with transferable objects? - Stack Overflow
shared-workers-and-the-sharedworker-interface