开发者

Retrieve an image from the server, store it in localStorage, and display it

This should be simple enough, but after wrestling with it for hours, I still can't get it to work. So far, all my attempts have resulted in the image becoming 'corrupted or truncated', according to firefox.

Retrieve the image from the server with a jquery-ajax call:

 $.ajax({
                async: false,
                url: db[key]["DocumentLink"],
                success: function (result2) {

Base64 encode the image, and store it in localStore:

In this example I'm using the jquery base64-encoding plugin, but I've tried several.

                        var dbKey = "Doc " + db[key]["ID"] + " " + db[key]["Title"];
                        console.log("storing: " + db[key]["DocumentLink"] + " in " + dbKey + "\n");
                        localStorage.removeItem(dbKey);
                        var base64Image = $.base64Encode(result2);
                        console.log(base64Image.length);
                        localStorage.setItem(dbKey, base64Image);
                       console.log("is stored: " + db[key]["DocumentLink"] + " in " + dbKey + "\n");
                }
})

Display the image with a data url:

function openImageFromDB(dbKey) {
    console.log("Trying to display image with key " + dbKey);
    var base64Img = localStorag开发者_如何学运维e.getItem(dbKey);
    document.getElementById("documentHolder").src='data:image/jpeg;base64,' + base64Img;
}

The corresponding img:

 <img id="documentHolder" alt="Image view placeholder" src="" />

However, on every try, firefox displays:

Image corrupt or truncated: data:image/jpeg;base64,77+977+977+977+9a<... much longer string>

The Url: points to a valid jpeg image, and the base64Image.length and the error message show that the var / localStorage actually contain what seems to be base64 encoded data.

Any ideas?


  • DEMO: http://so.lucafilosofi.com/retrieve-an-image-from-the-server-store-it-in-localstorage-and-display-it

Javascript (AJAX call)

function LoadImg(filename) {
    var xmlhttp;
    if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest();
    } else { // code for IE6, IE5
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {     
            document.getElementById("documentHolder").src = "data:image/png;base64," + xmlhttp.responseText;
        }
    };    
    xmlhttp.open("GET", 'load.php?LoadImg='+filename );
    xmlhttp.send(null);
}

PHP ( load.php )

<?php
 if (isset($_GET['LoadImg'])) {
  header("Content-Type: image/png");
  $file = file_get_contents($_GET['LoadImg']);
  echo base64_encode($file);
}
?>

Read this may help you:

  • Base 64 encode vs loading an image file
  • How to encode image data within an HTML file?
  • How can you encode a string to Base64 in JavaScript?
  • Get image data in JavaScript?

PS: maybe your Base64 is wrong?


Browsers have size limitations other than the localStorage limit of 5MB. The data for the <img src="data:image/jpeg;base64,..."> is also restricted and is usually much less than 5MB. The easiest way around this is to just pass the file-names via localStorage and let the browsers caching do the work.


Turns out, AJAX can't be used to reliably transfer binary data. The solution is to run the Base64 encoding server-side, and transfer the resulting string through AJAX.

The above php-code works. For whoever is looking for a ASP.Net / C# solution:

    public string Image(string relpath)
    {
        Response.ContentType = "image/jpeg";

        string base64;
        string filename = Request.PhysicalApplicationPath + relpath;
        try
        {
            using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                var buffer = new byte[fs.Length];
                fs.Read(buffer, 0, (int)fs.Length);
                base64 = Convert.ToBase64String(buffer);
            }
        }
        catch (IOException e)
        {
            return filename + " / " + e.Message;
        }
        return base64;
    }

Please note that this code is NOT SECURE to expose directly to the outer world. I personally use a wrapper-function that parses the path from a db.


You can get the data uri (which will contain the base 64 encoding) via JavaScript using the HTML5 canvas element.

        // I'm assuming here you've put the image in an <img> tag on the page already.
        // If not, you'll need to adapt this a bit, or perhaps this approach is just
        // not right for your situation.
        var image = document.getElementById('id-of-image-you-want');

        var canvas = w.document.createElement("canvas"); 
        canvas.width = image.width;
        canvas.height = image.height;

        var ctx = canvas.getContext("2d");
        ctx.drawImage(image, 0, 0);
        try {
            var dataUri = canvas.toDataURL();    
        } catch (e) {
            console.log("D'oh!"); // Improve this error handling, obviously.
        }

dataUri will now contain the data uri for the image which will contain, along with a short prefix, the base 64 encoding of the image.

Be sure to add detection for canvas support. IE 8 and older do not support it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜