通过sqlite的createObjectURL往返无法显示图像

时间:2013-07-28 05:49:09

标签: javascript image web-sql

我正在尝试使用createObjectURL显示从websql检索到的图像。我把下面的代码放在一起测试我是否可以保存和检索数据库中的数据。 在将数据保存到数据库之前,我可以创建objectURL并在屏幕上正确显示 - 从数据库中获取数据后,不显示任何内容 - 或者显示默认的“图标”。 我已经比较了从DB中写入和检索的数据,并且所有内容看起来都是相同的。我已经摸不着头脑,在网上搜索,并没有接近答案。 如果有任何建议/帮助我做错了,我将不胜感激。 编解码器来自herehere

我正在使用以下选项从命令行运行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 

1 个答案:

答案 0 :(得分:0)

所以这个问题已经解决了,但不是我想象的那样。首先,我使用ajax请求中的blob类型绕过了外部编码/解码函数(arraybuffer也有效,但还有一个额外的步骤来从中生成blob),并且必须使用FileReader / readAsDataURL将其转换为base64在存储到DB之前。

这样做的一个主要好处似乎是得到的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>