首页 > 编程笔记 > JavaScript笔记 > Ajax

AJAX发送和接收Blob对象(案例实战)

Blob(Binary Large Object)是一种 JavaScript 的数据类型,用于存储大量的二进制数据。Blob 对象中存储的数据没必要非得是 JavaScript 原生格式数据(或者没必要是 JavaScript 内部对象),例如,可以是 File 对象,它继承 Blob 对象,是 Blob 的一个分支或者说是一个子集。

发送 Blob 对象

在 JavaScript 中,所有 File 对象都是一个 Blob 对象,因此可以通过发送 Blob 对象的方法来发送文件。

【示例】下面示例在页面中显示一个“复制文件”按钮和一个进度条(progress 元素),单击“复制按钮”后,JavaScript 使用当前页面中所有代码创建一个 Blob 对象,然后通过将该 Blob 对象指定为 XMLHttpRequest 对象的 send() 方法的参数值的方法向服务器端发送该 Blob 对象,服务器端接收到该 Blob 对象后将其保存为一个文件,文件名为“副本”+ 当前页面文件的文件名(包括扩展名)。在向服务器端发送 Blob 对象的同时,页面中的进度条将同步显示发送进度。

前台页面

<script>
    window.URL = window.URL || window.webkitURL;
    function uploadDocument () {
        var bb = new Blob ([document.documentElement.outerHTML]);
        var xhr = new XMLHttpRequest();
        xhr.open('POST', 'test.php?fileName='+getFileName(), true);
        var progressBar = document.getElementById('progress');
        xhr.upload.onprogress = function (e) {
            if (e.lengthComputable) {
                progressBar.value = (e.loaded / e.total) * 100;
                document.getElementById("result").innerHTML='已完成进度:'+progressBar.value+'%';
            }
        }
        xhr.send(bb);
    }
    function getFileName () {  //获取当前页面的文件名
        var url = window.location.href;
        var pos = url.lastIndexOf("\\");
        if (pos == -1)  //pos == -1表示为本地文件
            pos = url.lastIndexOf("/");  //本地文件路径分割符为“/”
        var fileName = url.substring(pos + 1);  //从url中获得文件名
        return fileName;
    }
</script>
<input type="button" value="复制文件" onclick="uploadDocument()"><br/>
<progress min="0" max="100" value="0" id="progress"></progress>
<output id="result">

后台页面

<?php
    $str = file_get_contents('php://input');
    $fileName = '副本_'.$REQUEST['fileName'];
    $fp = fopen (iconv("UTF-8", "GBK", $fileName), 'w');
    fwrite($fp, $str);  //插入第一条数据
    fclose($fp);  //关闭文件
?>

目前,Chrome 浏览器支持在向服务器端发送数据时,同步更新进度条 progress 元素中所显示的进度。

演示效果如下图所示。

接收 Blob 对象

在 JavaScript 中,当 XMLHttpRequest 对象的 responseType 属性设置为 blob 时,服务器端响应数据将是一个 Bolb 对象。

目前,Firefox 8+、Chrome 19+、Opera 18+ 和 IE 10+ 版本浏览器支持将 XMLHttpRequest 对象的 responseType 属性值指定为 blob。

示例

下面示例设计在页面中显示一个“下载图片”按钮和一个“显示图片”按钮,单击“下载图片”按钮时,从服务器端下载一幅图片的二进制数据,在得到服务器端响应后创建一个 Blob 对象,并将该图片的二进制数据追加到 Blob 对象中,使用 FileReader 对象的 readAsDataURL() 方法将 Blob 对象中保存的原始二进制数据读取为 DataURL 格式的 URL 字符串,然后将其保存在 IndexDB 数据库中。单击“显示图片”按钮时,从 IndexDB 数据库中读取该图片的 DataURL 字符串,创建一个 img 元素,然后将该 URL 字符串设置为 img 元素的 src 属性值,在页面上显示该图片。
<script>
    window.indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
    window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
    window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
    window.IDBCursor = window.IDBCursor || window.webkitIDBCursor || window.msIDBCursor;
    window.URL = window.URL || window.webkitURL;
    var dbName = 'imgDB';
    var dbVersion = 20191017;
    var idb;
    function init () {
        var dbConnect = indexedDB.open (dbName, dbVersion);
        dbConnect.onsuccess = function (e) {
            idb = e.target.result;
        };
        dbConnect.onerror = function () { console.log('数据库连接失败'); };
        dbConnect.onupgradeneeded = function (e) {
            idb = e.target.result;
            var tx = e.target.transaction;
            tx.onabort = function (e) {
                console.log('对象仓库创建失败');
            };
            var name = 'img';
            var optionalParameters = {
                keyPath : 'id',
                autoIncrement : true
            };
            var store = idb.createObjectStore (name, optionalParameters);
            console.log('对象仓库创建成功');
        };
    }
    function downloadPic () {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'image/1.png', true);
        xhr.responseType = 'blob';
        xhr.onload = function (e) {
            if (this.status == 200) {
                var bb = new Blob([this.response]);
                var reader = new FileReader();
                reader.readAsDataURL (bb);
                reader.onload = function (f) {
                    var result = document.getElementById("result");
                    //在indexDB数据库中保存二进制数据
                    var tx = idb.transaction(['img'], "readwrite");
                    tx.oncomplete = function () { console.log('保存数据成功'); }
                    tx.onabort = function () { console.log('保存数据失败'); }
                    var store = tx.objectStore ('img');
                    var value = { img : this.result };
                    store.put (value);
                }
            }
        };
        xhr.send();
    }
    function showPic () {
        var tx = idb.transaction (['img'], "readonly");
        var store = tx.objectStore ('img');
        var req = store.get(1);
        req.onsuccess = function () {
            if (this.result == undefined) {
                console.log("没有符合条件的数据");
            } else {
                var img = document.createElement ('img');
                img.src = this.result.img;
                document.body.appendChild (img);
            }
        }
        req.onerror = function () {
            console.log("获取数据失败");
        }
    }
</script>
<body onload="init()">
    <input type="button" value="下载图片" onclick="downloadPic()"><br />
    <input type="button" value="显示图片" onclick="showPic()"><br />
    <output id="result"></output>
</body>

操作步骤

1) 当用户单击“下载图片”按钮时,调用 downloadPic() 函数,在该函数中,XMLHttpRequest 对象从服务器端下载一幅图片的二进制数据,在下载时将该对象的 responseType 属性值指定为 blob 对象。
var xhr = new XMLHttpRequest();
xhr.open('GET', 'image/1.png', true);
xhr.responseType = 'blob';

2) 在得到服务器端响应后,使用该图片的二进制数据创建一个 Blob 对象。然后创建一个 FileReader 对象,并且使用 FilReader 对象的 readAsDataURL() 方法将 Blob 对象中保存的原始二进制数据读取为 DataURL 字符串,然后将其保存在 IndexDB 数据库中。

3) 单击“显示图片”按钮时,从 IndexDB 数据库中读取该图片的 DataURL 格式的 URL 字符串,然后创建一个用于显示图片的 img 元素,然后将该 URL 字符串设置为 img 元素的 src 属性值,在该页面上显示下载的图片。

在浏览器中预览,单击页面中“下载图片”按钮,脚本从服务器端下载图片并将该图片二进制数据的 DataURL 格式的  URL 字符串保存在 indexDB 数据库中,保存成功后在弹出的提示信息框中显示“保存数据成功”,效果如下图所示。


单击“显示图片”按钮,脚本从 indexDB 数据库中读取图片的 DataURL 格式的 URL 字符串,并将其指定为 img 元素的 src 属性值,在下面页面中显示该图片,效果如下:

所有教程

优秀文章