菜鸟教程小白 发表于 2022-12-12 09:08:16

javascript - 尝试在 iOS Safari 8 中存储 blob 会引发 DataCloneError


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

<pre><code>DataCloneError: DOM IDBDatabase Exception 25: The data being stored could
not be cloned by the internal structured cloning algorithm
</code></pre>

<p>这发生在我的代码和这个例子中:<a href="http://robnyman.github.io/html5demos/indexeddb/" rel="noreferrer noopener nofollow">http://robnyman.github.io/html5demos/indexeddb/</a> </p>

<p>这是导致我的代码(和上面的示例)失败的行:</p>

<pre><code>//This throws the error
var put = transaction.objectStore(&#34;elephants&#34;).put(blob, &#34;image&#34;);
</code></pre>

<p>有解决办法吗? blob 是否需要首先进行 base64 编码(就像您必须使用 WebSQL 一样)?</p>

<p><strong>我的代码</strong> <em>(适用于桌面版 Chrome/Firefox 和 Android 版 Chrome/Firefox):</em></p>

<pre><code>var xhr = new XMLHttpRequest();
var blob;

//Get the Video
xhr.open( &#34;GET&#34;, &#34;test.mp4&#34;, true );

//Set as blob
xhr.responseType = &#34;blob&#34;;

//Listen for blob
xhr.addEventListener(&#34;load&#34;, function () {
      if (xhr.status === 200) {
            blob = xhr.response;

            //Start transaction
            var transaction = db.transaction([&#34;Videos&#34;], &#34;readwrite&#34;);

            //IT FAILS HERE
            var put = transaction.objectStore(&#34;Videos&#34;).put(blob, &#34;savedvideo&#34;);

      }
      else {
            console.log(&#34;ERROR: Unable to download video.&#34; );
      }
}, false);

xhr.send();
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>出于某些<em>奇怪</em>原因(这是一个错误),就像 iOS Safari 7 的 WebSQL 一样,您<strong>不能</strong>在 iOS Safari 8 上的 IndexedDB 中存储 BLOB。您必须转换它到base64,然后它将存储而不会出错。 (我再说一遍,这是一个错误)</p>

<p>所以,把代码改成这样:</p>

<p><strong>更改响应类型</strong></p>

<pre><code>xhr.responseType = &#34;arraybuffer&#34;;
</code></pre>

<p><strong>从 XMLHttpRequest 检索后存储在数据库中</strong></p>

<pre><code>//We&#39;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 = String.fromCharCode(uInt8Array);
}

//Make into a string
var data = binaryString.join(&#39;&#39;);

//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([&#34;Videos&#34;], &#34;readwrite&#34;);
var put = transaction.objectStore(&#34;Videos&#34;).put(base64, &#34;savedvideo&#34;);
</code></pre>

<p><strong>从 IndexedDB 检索后,将其转换回来:</strong></p>

<pre><code>//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 &lt; len; ++i )
{
    //Get back as int
    asArray = data.charCodeAt(i);   
}

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

//Make into object url for video source
var videoURL = URL.createObjectURL(blob);
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于javascript - 尝试在 iOS Safari 8 中存储 blob 会引发 DataCloneError,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/32901733/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/32901733/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: javascript - 尝试在 iOS Safari 8 中存储 blob 会引发 DataCloneError