Javascript 尝试在iOS Safari 8中存储blob抛出数据克隆错误

Javascript 尝试在iOS Safari 8中存储blob抛出数据克隆错误,javascript,ios,html,safari,indexeddb,Javascript,Ios,Html,Safari,Indexeddb,当我尝试存储blob(通过XMLHttpRequestGET请求检索)时,iOS 8.4上的Safari会抛出错误: DataCloneError: DOM IDBDatabase Exception 25: The data being stored could not be cloned by the internal structured cloning algorithm 我的代码和本例都会出现这种情况: 这一行导致我的代码(以及上面的示例)失败: 是否有解决方法?是否需要首先对blo

当我尝试存储blob(通过
XMLHttpRequest
GET
请求检索)时,iOS 8.4上的Safari会抛出错误:

DataCloneError: DOM IDBDatabase Exception 25: The data being stored could
not be cloned by the internal structured cloning algorithm
我的代码和本例都会出现这种情况:

这一行导致我的代码(以及上面的示例)失败:

是否有解决方法?是否需要首先对blob进行base64编码(就像您必须使用WebSQL一样)

我的代码(适用于Android上的桌面Chrome/Firefox和Chrome/Firefox):

出于某种奇怪的原因(这是一个bug),就像iOS Safari 7的WebSQL一样,无法在iOS Safari 8的IndexedDB中存储BLOB。您必须将其转换为base64,然后它将毫无错误地存储。(我重复,这是一个bug)

因此,将代码更改为:

更改响应类型

xhr.responseType = "arraybuffer";
从XMLHttpRequest检索后存储在数据库中

//We'll make an array of unsigned ints to convert
var uInt8Array = new Uint8Array(xhr.response);
var i = uInt8Array.length;
var binaryString = new Array(i);
while (i--)
{
    //Convert each to character
    binaryString[i] = String.fromCharCode(uInt8Array[i]);
}

//Make into a string
var data = binaryString.join('');

//Use built in btoa to make it a base64 encoded string
var base64 = window.btoa(data);

//Now we can save it
var transaction = db.transaction(["Videos"], "readwrite");
var put = transaction.objectStore("Videos").put(base64, "savedvideo");
从IndexedDB中检索后,将其转换回:

//Convert back to bytes
var data = atob( event.target.result );

//Make back into unsigned array
var asArray = new Uint8Array(data.length);

for( var i = 0, len = data.length; i < len; ++i ) 
{
    //Get back as int
    asArray[i] = data.charCodeAt(i);    
}

//Make into a blob of proper type
var blob = new Blob( [ asArray.buffer ], {type: "video/mp4"} );

//Make into object url for video source
var videoURL = URL.createObjectURL(blob);
//转换回字节
var数据=atob(event.target.result);
//返回到无符号数组
var asArray=新的Uint8Array(data.length);
对于(变量i=0,len=data.length;i谢谢你花时间把它记录在这里。你碰到过其他应该与此处链接的堆栈溢出问题吗?还是在其他StAdExchange网络站点有问题?还有,你知道是否有一个开放的Safari /WebKIT bug?如果没有,请考虑提高一个。(如果已经有一个打开的,或者如果你打开了一个),也可以从这里链接到它。@sideshowbarker我确实在苹果的bug数据库中创建了一个bug,而不是webkit,这不是webkit问题(在他们关闭webkit之前在Chrome中工作)Safari的实现是错误的。我发现一些老问题可能来自经历过同样事情的人(不确定,因为他们的代码不存在)但是没有回答。给出了我的+1。我通过将db事务包装在一个try catch中来解决这个问题。如果catch收到一个带有
event.type===25
的错误,我会在存储之前进行base64转换。然后在从idb检索它之后进行类型检查,并在必要时转换回blob(在许多用例中,可以只使用base64字符串)。这是一个长期存在的问题,希望Safari能够解决,因为这些操作非常昂贵。。。
//We'll make an array of unsigned ints to convert
var uInt8Array = new Uint8Array(xhr.response);
var i = uInt8Array.length;
var binaryString = new Array(i);
while (i--)
{
    //Convert each to character
    binaryString[i] = String.fromCharCode(uInt8Array[i]);
}

//Make into a string
var data = binaryString.join('');

//Use built in btoa to make it a base64 encoded string
var base64 = window.btoa(data);

//Now we can save it
var transaction = db.transaction(["Videos"], "readwrite");
var put = transaction.objectStore("Videos").put(base64, "savedvideo");
//Convert back to bytes
var data = atob( event.target.result );

//Make back into unsigned array
var asArray = new Uint8Array(data.length);

for( var i = 0, len = data.length; i < len; ++i ) 
{
    //Get back as int
    asArray[i] = data.charCodeAt(i);    
}

//Make into a blob of proper type
var blob = new Blob( [ asArray.buffer ], {type: "video/mp4"} );

//Make into object url for video source
var videoURL = URL.createObjectURL(blob);