0

我正在尝试使用 createObjectURL 显示从 websql 检索到的图像。我将下面的代码放在一起来测试我是否可以从数据库中保存和检索数据。在将图像保存在数据库中之前,我可以创建 objectURL 并将其正确显示在屏幕上——然而,在从数据库中获取数据之后,什么都没有显示——或者更确切地说,显示的是默认的“图标”。我比较了从数据库中写入和检索的数据,一切似乎都是相同的。我已经为此挠头并搜索了网络,并且离答案更近了。对于我做错的任何建议/帮助,我将不胜感激。编解码器来自这里这里

我正在使用以下选项从命令行运行 chrome (28.0.1500.71):

google-chrome --disable-web-security --allow-file-access-from-files --unlimited-storage

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- pick any encode/decode pair - this pair seemed to work fine -->
<script src="js/base64_encode.js"></script>
<script src="js/base64_decode.js"></script>

<script>
function run(){
    var gendate = new Date().getTime()
    var encode = base64_encode; // replace this with whatever encode/decode pair
    var decode = base64_decode; // replace this with whatever encode/decode pair
    var codec = "base64_encode_decode";
    var input, b64input;
    var output, b64output;
    var filename = "small.png"  //add any file in your system
    var key = gendate+filename;

    console.log("Codec: "+ codec);
    var db = window.openDatabase("tmpdb", "1.0", "Sql Test DB", 5 * 1024 * 1024, function(){
        console.log("success")
    }, function(e){
        console.log(e);
    });

    function put(){
        var req = new XMLHttpRequest();
        req.open('GET', filename , false);
        req.overrideMimeType('text\/plain; charset=x-user-defined');
        req.onerror = function(){
            console.log("ERROR: "+req.StatusText);
        }
        req.onload = function () {
            console.log("Input file size: " +req.response.length);
            var start = new Date().getTime()
            input = showImage(req.response);
            var data = encode(req.response);
            b64input = data;
            console.log("encode duration: "+ (new Date().getTime()-start));
            console.log("Encoded size: " + data.length);
            function _run () {
                console.log("Wrote " + key);
                db.transaction( function (tx) {
                    tx.executeSql('CREATE TABLE IF NOT EXISTS tmptable  (key, body NONE)');
                    tx.executeSql('INSERT INTO tmptable (key, body) VALUES (?, ?)',[key, data]);
                    get();
                });
            }
            _run();
        }
        req.send(null);
    }

    function get(){
        db.transaction( function (tx) {
            tx.executeSql('Select body from tmptable where key=?', [key],
                function(tx, result){
                    var start = new Date().getTime()
                    b64output = result.rows.item(0).body;
                    var data = decode(result.rows.item(0).body)
                    output = data;
                    console.log("decode duration: "+ (new Date().getTime()-start));
                    console.log("Output data size: "+ data.length);
                    output = showImage(data);
                    if (b64input === b64output) {
                        console.log("b64 matched")
                    } else {
                        console.log("b64 not matched");
                    }
                    compareArray(input, output)
                }, function(err){
                    console.log("ERROR: ", err)
                });
        });
    }

    function compareArray(input, output){
        var match = true;
        for (var i = 0; i < input; i++) {
            if (input[i] !== output[i]){
                console.log("Arrays not matched at: " +i);
                match = false;
                break;
            }
        }
        if (match) { console.log("Arrays match")};
    }
    function showImage( data ) {
        var byteArray = new Uint8Array(data.length);
        for (var i = 0; i < data.length; i++) {
            byteArray[i] = data.charCodeAt(i) & 0xff;
        }
        var blob = new Blob([byteArray.buffer], {type:"image/png"});
        var img = document.createElement('img');
        img.onload = function() {
            window.URL.revokeObjectURL(blob);
        };
        img.src = window.URL.createObjectURL(blob);
        document.body.appendChild(img);
        return byteArray;
    }
    put();
}
</script>
<title>Insert title here</title>
</head>
<body onload="run()">
</body>
</html>

控制台输出如下:

Codec: base64_encode_decode
Input file size: 670 
encode duration: 4 
Encoded size: 896 
Wrote 1374988636651small.png 
decode duration: 1 
Output data size: 670 
b64 matched 
Arrays match 
4

1 回答 1

0

所以问题得到了解决,但不是以我预期的方式。一方面,我在 ajax 请求中使用 blob 类型绕过了外部编码/解码函数(arraybuffer 也可以工作,但有一个额外的步骤可以从中生成 blob),并且必须使用 FileReader/readAsDataURL 将其转换为base64 存储在数据库中之前。

这样做的主要好处之一似乎是生成的 base64 编码与标准 atob 函数兼容。我永远无法让 btoa 函数将二进制文件转换为 base64 - 如果按预期工作,那么可以从该过程中删除更多步骤。

将其转换回 blob 时,我使用 atob 制作 base64 二进制文件,然后通过 ArrayBuffer 将其转换为 blob(代码是从网上借来的 - 我不记得确切的位置,对此我深表歉意,但是这是我发现唯一可以正常工作的转换 - 如果作者识别代码 - 请发布带有 URL 的评论,以便我们将来受益),然后使用 createObjectURL 正确显示。

尽管在从网上借用建议和示例后,我最终确实使往返工作正常,但这似乎是一种相当迂回的解决方案。如果有人有更好/更简单的解决方案 - 请随时添加评论。

在我看来,base64 编码和解码需要一些额外的步骤——而且我无法将 blob/二进制文件直接存储/检索到 sqlite 中——或者有人发现了一种方法吗?如果是这样,请添加评论:)

我最终使用的代码如下(减去控制台日志),供我和其他任何人将来参考。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script>
function run(){
    var gendate = new Date().getTime()
    var filename = "small.png"  //add any file in your system
    var key = gendate+filename;
    var db = window.openDatabase("sqldb", "1.0", "Sql Test DB", 5 * 1024 * 1024, function(){
        console.log("success")
    }, function(e){
        console.log(e);
    });

    function put(){
        var req = new XMLHttpRequest();
        req.open('GET', filename , false);
        req.overrideMimeType('text\/plain; charset=x-user-defined');
        req.responseType = "blob";
        req.onerror = function(){
            console.log("ERROR: "+req.StatusText);
        }
        req.onload = function () {
            showImage(req.response);
            var reader = new FileReader();
            reader.onloadend = function(e) {
                data = reader.result.replace(/^data:.+;base64,/, '');
                db.transaction( function (tx) {
                    tx.executeSql('CREATE TABLE IF NOT EXISTS tmptable  (key, body NONE)');
                    tx.executeSql('INSERT INTO tmptable (key, body) VALUES (?, ?)',[key, data]);
                    get();
                });
            };
            reader.readAsDataURL(req.response);
        }
        req.send(null);
    }

    function get(){
        db.transaction( function (tx) {
            tx.executeSql('Select body from tmptable where key=?', [key],
                function(tx, result){
                    var data = atob(result.rows.item(0).body)
                    var barray = new Uint8Array(data.length);
                    for (var i = 0; i < data.length; i++) {
                        barray[i] = data.charCodeAt(i) & 0xff;
                    }
                    blob = new Blob([barray], {type:"image/png"});
                    showImage(blob);
                }, function(err){
                    console.log("ERROR: ", err)
                });
        });
    }
    function showImage( blob) {
        var img = document.createElement('img');
        img.onload = function() {
            window.URL.revokeObjectURL(blob);
        };
        img.src = window.URL.createObjectURL(blob);
        document.body.appendChild(img);
    }
    put();
}
</script>
<title>Insert title here</title>
</head>
<body onload="run()">
</body>
</html>
于 2013-07-30T18:48:12.103 回答