3

I am trying to save a image to localstorage and fetch the same back when is required,am confused on how to save a image as i have referred question related to my same question but they are complicated, Finally i got some thing which looks perfect to me but i am confused how to use the code to save the image on local storage
Hear is the code in JSFIDDEL

Html:

<input type="file" id="bannerImg"  />


<img src="" id="tableBanner" />

JS:

bannerImage = document.getElementById('bannerImg');
imgData = getBase64Image(bannerImage);
localStorage.setItem("imgData", imgData);


function getBase64Image(img) {
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;

    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);

    var dataURL = canvas.toDataURL("image/png");

    return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}

function fetchimage ()
{
var dataImage = localStorage.getItem('imgData');
var bannerImg = document.getElementById('tableBanner');
 bannerImg.src = "data:image/png;base64," + dataImage;
}
  • localstorage space available is really varying from browsers to others ([see this good post about it](http://www.html5rocks.com/en/tutorials/offline/quota-research/)). I think that average is 3~5MB, be sure your image is not heavier. – Kaiido Aug 06 '15 at 09:11
  • @Kaiido, thanks for the information i was not knowing about this do you have any idea to resize the image ??? –  Aug 06 '15 at 10:25
  • @Kaiido, i have zero clue how to add if u really dont mind can u join me hear https://jsfiddle.net/cv0gx6yL/#&togetherjs=nOmAGPoeQx –  Aug 06 '15 at 11:20
  • Was kind of long so added it as an answer. – Kaiido Aug 07 '15 at 04:31

3 Answers3

2

You just lack a FileReader to read the input file to dataURL. Jsfiddle

Html:

<input type="file" id="bannerImg"  />
<img src="" id="tableBanner" />
<!-- for result output -->
<div id="res"></div>

javascript:

// Get all variables
var bannerImage = document.getElementById('bannerImg');
var result = document.getElementById('res');
var img = document.getElementById('tableBanner');

// Add a change listener to the file input to inspect the uploaded file.
bannerImage.addEventListener('change', function() {
    var file = this.files[0];
    // Basic type checking.
    if (file.type.indexOf('image') < 0) {
        res.innerHTML = 'invalid type';
        return;
    }

    // Create a file reader
    var fReader = new FileReader();

    // Add complete behavior
    fReader.onload = function() {
        // Show the uploaded image to banner.
        img.src = fReader.result;

        // Save it when data complete.
        // Use your function will ensure the format is png.
        localStorage.setItem("imgData", getBase64Image(img));
        // You can just use as its already a string.
        // localStorage.setItem("imgData", fReader.result);
    };

    // Read the file to DataURL format.
    fReader.readAsDataURL(file);
});

function getBase64Image(img) {
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;

    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);

    var dataURL = canvas.toDataURL("image/png");

    return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}

function fetchimage () {
    var dataImage = localStorage.getItem('imgData');
    img.src = "data:image/png;base64," + dataImage;
    // If you don't process the url with getBase64Image, you can just use
    // img.src = dataImage;
}

// Call fetch to get image from localStorage.
// So each time you reload the page, the image in localstorage will be 
// put on tableBanner
fetchimage();

Not that the jsfiddle execute this script onload, so you may wrap them in window.onload in your own site.

fuyushimoya
  • 9,715
  • 3
  • 27
  • 34
  • Because the image type should be `image/png` or `image/jpeg`, and use that function will gurantee to get `image/png`, I'll update it then. – fuyushimoya Aug 06 '15 at 09:25
  • I just first think OP has something to do with that imageurl, as he is stripping the `data....base64` part. He may have some concern to it, and I think its better to left the OP to decide whether store it directly or use another process, as the answer point is about `FileReader` :P. – fuyushimoya Aug 06 '15 at 09:27
  • Ok, then I'll comment at the code to state that the `getBase64Image` is not a must do if OP is only want to store the image. – fuyushimoya Aug 06 '15 at 09:31
  • @fuyushimoya I have a quick question if u dont mind can the image be saved only on a button click –  Aug 06 '15 at 09:39
  • Yes, move the `localStorage.setItem("imgData", getBase64Image(img));` to the click callback to that button. Then it'll only show the image when uploaded, not save to localStorage until you click the button mentioned. – fuyushimoya Aug 06 '15 at 09:40
1

Because of the limited storage quota you've got with localStorage, you may need to check the size of the uploaded image.

Here is one way, based on @fuyushimoya's answer, if you don't need to convert every type of image to png. Otherwise, you're kind of screwed since it's one of the heaviest image type.

This solution may not be the best but it seems to handle a few cases :

JS

// Get all variables
var bannerImage = document.getElementById('bannerImg');
var result = document.getElementById('res');
var img = document.getElementById('tableBanner');

bannerImage.addEventListener('change', function() {
  var file = this.files[0];
  // declare a maxSize (3Mb)
  var maxSize = 3000000;

  if (file.type.indexOf('image') < 0) {
    res.innerHTML = 'invalid type';
    return;
  }
  var fReader = new FileReader();
  fReader.onload = function() {
    img.onload = function() {
      // if localStorage fails, it should throw an exception
      try {
        // pass the ratio of the file size/maxSize to your toB64 func in case we're already out of scope
        localStorage.setItem("imgData", getBase64Image(img, (file.size / maxSize), file.type));
      } catch (e) {
        var msg = e.message.toLowerCase();
        // We exceeded the localStorage quota
        if (msg.indexOf('storage') > -1 || msg.indexOf('quota') > -1) {
          // we're dealing with a jpeg image :  try to reduce the quality
          if (file.type.match(/jpe?g/)) {
            console.log('reducing jpeg quality');
            localStorage.setItem("imgData", getBase64Image(img, (file.size / maxSize), file.type, 0.7));
          }
          // we're dealing with a png image :  try to reduce the size
          else {
            console.log('reducing png size');
            // maxSize is a total approximation I got from some tests with a random pixel generated img
            var maxPxSize = 750000,
              imgSize = (img.width * img.height);
            localStorage.setItem("imgData", getBase64Image(img, (imgSize / maxPxSize), file.type));
          }
        }
      }
    }
    img.src = fReader.result;
  };

  fReader.readAsDataURL(file);
});

function getBase64Image(img, sizeRatio, type, quality) {
  // if we've got an svg, don't convert it, svg will certainly be lighter than any pixel image
  if (type.indexOf('svg+xml') > 0) return img.src;

  // if we've got a jpeg
  if (type.match(/jpe?g/)) {
    // and the sizeRatio is okay, don't convert it
    if (sizeRatio <= 1) return img.src;
  }
  // if we've got some other image type
  else type = 'image/png';

  if (!quality) quality = 1;
  var canvas = document.createElement("canvas");
  // if our image file is too large, then reduce its size
  canvas.width = (sizeRatio > 1) ? (img.width / sizeRatio) : img.width;
  canvas.height = (sizeRatio > 1) ? (img.height / sizeRatio) : img.height;

  var ctx = canvas.getContext("2d");
  ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  // if we already tried to reduce its size but it's still failing, then reduce the jpeg quality
  var dataURL = canvas.toDataURL(type, quality);

  return dataURL;
}

function fetchimage() {
  var dataImage = localStorage.getItem('imgData');
  img.src = dataImage;
}

// Call fetch to get image from localStorage.
fetchimage();

HTML

<input type="file" id="bannerImg" />
<img src="" id="tableBanner" />
<div id="res"></div>

▶︎ Fiddle

Kaiido
  • 123,334
  • 13
  • 219
  • 285
1

Usa esta directiva:

directives.directive('baseSixtyFourInput', ['$window', function($window) {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, elem, attrs, ngModel) {
            var fileObject = {};
            scope.readerOnload = function(e) {
                var base64 = _arrayBufferToBase64(e.target.result);
                fileObject.base64 = base64;
                scope.$apply(function() {
                    ngModel.$setViewValue(angular.copy(fileObject));
                });
            };

            var reader = new FileReader();
            reader.onload = scope.readerOnload;

            elem.on('change', function() {
                var file = elem[0].files[0];
                fileObject.filetype = file.type;
                fileObject.filename = file.name;
                fileObject.filesize = file.size;
                reader.readAsArrayBuffer(file);
            });

            //http://stackoverflow.com/questions/9267899/arraybuffer-to-base64-encoded-string
            function _arrayBufferToBase64(buffer) {
                var binary = '';
                var bytes = new Uint8Array(buffer);
                var len = bytes.byteLength;
                for (var i = 0; i < len; i++) {
                    binary += String.fromCharCode(bytes[i]);
                }
                return $window.btoa(binary);
            }
        }
    };
}]);
Fernando Torres
  • 460
  • 7
  • 24