3

I'm having trouble finding how exactly I would store an uploaded image in localStorage, as inputted by a user in my options page. There isnt too much documentation on how to do it because for awhile it was a known error and I couldnt find any examples on Stack. There's some examples on how to save an image already on a page but nothing on an inputed image.

All i have is the HTML, but I imagine that the javascript running in the back needs to access the value of the input or something (?).

<input id="uploadImage" type="file" accept="image/*" />

Then after the user chooses a file, the value of the input is C:\fakepath\some_image.jpg. I dont want to store the filepath but store the actual image, if possible.

$("#uploadImage").change(function(){
    alert($("#uploadImage").val());
});

EDIT:

I found a sample on how to do it from this stack topic, but the filepath that I get from $("#uploadImage").val() doesnt work (So I dont know if this method work work even if the filepath was valid)

var img = new Image();
img.src = $("#uploadImage").val();
img.load = function() {
    var canvas = document.createElement('canvas');
    document.body.appendChild(canvas);
    var context = canvas.getContext('2d');
    context.drawImage(img, 0, 0);
    var data = context.getImageData(x, y, img.width, img.height).data;
    localStorage['uploadedImage'] = data; // save image data
};
Community
  • 1
  • 1
Jordan
  • 315
  • 1
  • 7
  • 19

3 Answers3

2

This requires the FileReader API, and is just a modified version of this answer (ref: Loading an image to a <img> from <input file>):

    var input = document.getElementById('uploadImage');
    input.onchange = function(evt){
        var tgt = evt.target || window.event.srcElement, 
            files = tgt.files;

        if (FileReader && files && files.length) {
            var fr = new FileReader();
            fr.onload = function () {
                localStorage['foo'] = fr.result;
            }
            fr.readAsDataURL(files[0]);
        }
    }

You could then apply it as a background image by doing something like:

var el = document.querySelector('body');
el.style.backgroundImage = 'url(' + localStorage['foo'] + ')';
Community
  • 1
  • 1
Mister Epic
  • 15,703
  • 11
  • 68
  • 126
  • So after this i'm confused. You're storing the image data as a string in localStorage (correct?). Then to construct an image (and for my purpose, set it as the background) it would look like- `$('body').css({"background": localStorage['foo']});` – Jordan Mar 15 '16 at 18:51
  • @Jordan Updated my answer, didn't have time to test it, let me know if you still have issues. – Mister Epic Mar 15 '16 at 18:58
  • Thank you very much! This wasn't the whole thing I needed but you gave me a working example and I was able to go from there – Jordan Mar 15 '16 at 19:16
1

Well, this is how you can do it:

  1. First of all read the file using FileAPI. A good example could be found here
  2. After you have a file content you have another problem: how to store it. LocalStorage accepts only strings, so you would need to convert your binary image file to Base64, e.g. like they do here
  3. And finally you can render your image later using data-URI

As you may see, this isn't that easy, but still if you follow the instructions you can do it.

Community
  • 1
  • 1
smnbbrv
  • 19,108
  • 9
  • 62
  • 100
  • I see, but how do I get around the filepath issue? (see my edit) – Jordan Mar 15 '16 at 17:07
  • do you want to get the image data from the server? My proposal is to read the file before you upload it, so, I guess, there is no filepath issue in this case. If you want to download the image from server why don't you just get it as Base64 from server? And why actually do you need the image in a localStorage then? – smnbbrv Mar 15 '16 at 17:10
  • The image is being uploaded by the user, this is a chrome extension (as stated in question title) – Jordan Mar 15 '16 at 17:13
1

You can't open file:// URLs from http:// or https:// URLs, as this breaches security (see this question), however, if you are just running your HTML page from a file:// URL it should work with your code.

You do need to make sure the canvas element is the same dimensions as the image though, and also it's best practice to specify the src attribute after the onload callback function just in case it loads too fast for the onload callback binding to be in place.

You should also make sure you are using the correct localStorage API to store and retrieve items from localStorage.

canvas.toDataURL() is also a neater way of getting the Base64 string for the image data.

Here's some updated code.

var img = new Image();
img.onload = function() {
    var canvas = document.createElement('canvas');
    canvas.width = this.width;
    canvas.height = this.height;
    document.body.appendChild(canvas);

    var context = canvas.getContext('2d');
    context.drawImage(img, 0, 0);

    var data = canvas.toDataURL();
    localStorage.setItem('uploadedImage', data); // save image data
};
img.src = 'file://' + $("#uploadImage").val();

Then to get the item and use it as an image on your page, you could use:

var $img = $('<img />', { src: localStorage.getItem('uploadedImage') });
$('body').append($img);
Community
  • 1
  • 1
toomanyredirects
  • 1,892
  • 14
  • 22
  • I'm still having trouble with the filepath of the image that the user uploads, `Failed to load resource: net::ERR_UNKNOWN_URL_SCHEME` and I dont think there are any permissions that I can request because this is just an extension and not an app – Jordan Mar 15 '16 at 17:22
  • I'm unsure that `img.src = $("#uploadImage").val();` will provide the desired result. The value of the file input will not be usable in this fashion. In Chrome this resolves to something like `c:\fakepath\foo.png`. – Mister Epic Mar 15 '16 at 17:25
  • Ah yes, thanks @MisterEpic, @Jordan I think you'll need that `img.src` bit to be `img.src = 'file://' + $('#uploadImage').val();` **answer updated** – toomanyredirects Mar 15 '16 at 17:28
  • @Mister, does that mean that this really isnt possible? And @too, that didnt fix it. Its a valid URL but it just gives me a white background when I run this: `$('body').css({"background": "url("+img.src+")"});` – Jordan Mar 15 '16 at 17:46
  • @Jordan It is absolutely possible so long as your browser supports `FileReader`. My answer should work for you. – Mister Epic Mar 15 '16 at 18:05