13

I am trying to save blob data (favicon) retrieved via AJAX, to localStorage.

Code :

var xhr = new XMLHttpRequest();
xhr.open('GET', 
'http://g.etfv.co/http://www.google.com',
true);
xhr.responseType = "blob";
xhr.onload = function(e){ //Stringify blob...
    localStorage['icon'] = JSON.stringify(xhr.response);
    //reload the icon from storage
    var fr = new FileReader();
    fr.onload = 
        function(e) {
            document.getElementById("myicon").src = fr.result;
        }
    fr.readAsDataURL(JSON.parse(localStorage['icon']));
    }
xhr.send(null);

The code is adapted from here with minor modifications to make it work with localStorage. localStorage saves all data as strings, so blobs need to be stringified somehow before being saved.

JSON doesn't deal with blobs as one of it's supported types, so it's no surprise that this code fails.

Is there any way to get the blob into localStorage?

4
  • Not sure, just a shot but if your request response was the binary itself, then you save it directly on localStorage.. Commented Jan 8, 2014 at 23:27
  • Ah sorry, I was thinking of indexeddb, never mind. Commented Jan 8, 2014 at 23:28
  • possible duplicate of stackoverflow.com/questions/14113278/… Commented Jan 8, 2014 at 23:28
  • @XGreen Yo man!. That is not a question, that's a doctoral thesis. Will check that out anyway. Commented Jan 8, 2014 at 23:34

3 Answers 3

15

Just store the blob as a data uri in local storage

var xhr = new XMLHttpRequest();
xhr.open('GET', 
'http://g.etfv.co/http://www.google.com',
true);
xhr.responseType = "blob";
xhr.onload = function(e){ //Stringify blob...
    //reload the icon from storage
    var fr = new FileReader();
    fr.onload = 
        function(e) {
            localStorage['icon'] = e.target.result;
            document.getElementById("myicon").src = localStorage['icon'];
        }
    fr.readAsDataURL(xhr.response);
}
xhr.send(null);
Sign up to request clarification or add additional context in comments.

5 Comments

Well, at least this is inefficient. Try to compare xhr.response.size() with e.target.result.length. But I may resort to that in the end.
Its just over 33% larger (base64 encoding), but this is the only way I know of to convert the blob into a usable string. Maybe if you find a better way you can post it as an answer.
If I am going to store favicons they are going to be many, plus other data, so all the favicons can take 1mb from the available 5mb
Assuming the original favicon was e.g. PNG file, it's not going to compress anymore.
0

We can now use the modern fetch API to do the job.


const getFromCacheOrDownload = async (url) => {
    const base64CachedImg = localStorage.getItem(url)
    if (base64CachedImg) {
        const response = await fetch(base64CachedImg)
        const blob = await response.blob()
        return URL.createObjectURL(blob)
    } else {
        const response = await fetch(url)
        if (response.status === 429) {
            console.log('too many requests')
        }
        const blob = await response.blob()
        const imageUrl = URL.createObjectURL(blob)
        const base64String = (await convertBlobToBase64(blob))
        localStorage.setItem(url, base64String)
        return imageUrl
    }
}

The above code will try to get the picture from the cache. If not, it downloads it and store it in the cache.

1 Comment

At this stage we might just as well be using Cache storage instead of localStorage as well...
0

You asked several questions at once, why the request code, there are no problems in it. The question is how to save a string in localStorage, because a string is the same binary data, you will just have a problem if you copy it because of the zero byte. In general, the essence is simple, convert blob to Uint8Array, go through the bytes extracting numbers and save them in the characters of the string text += String.fromCharCode(var_Uint8Array[i]) save the string in localStorage, it's elementary simple. Well, and the encoding should be eight-bit accordingly.

1 Comment

This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.