106
<input type="file" id="asd"/>

I would like to get the image in base64 once the user chose that (before submitting the form)

Something like :

$(input).on('change',function(){
  var data = $(this).val().base64file(); // it is not a plugin is just an example
  alert(data);
});

I read about File API and other stuffs, I would like a simple and cross-browsers solution (IE6/IE7 excluded obviously)

Any help appreciated thanks.

dark_ruby
  • 7,646
  • 7
  • 32
  • 57
bombastic
  • 2,961
  • 8
  • 20
  • 18
  • 1
    And what did you not understand about the HTML5 File api? What did you try? What did not work? – epascarello Jul 17 '13 at 21:03
  • @epascarello they are not fully supported actually http://caniuse.com/#feat=fileapi i need a work around, especially cause android versions are still used (old versions) as well as for old iOS versions, and i also would like to involve IE9 which is still used a lot :P – bombastic Jul 17 '13 at 21:04
  • a workaround for what? What are you trying to do with the file? `base64file()` - is that a plugin? – David Hellsing Jul 17 '13 at 21:05
  • @David i just would like to get the base64 file once the user select the file from his pc, base64file() is just an example – bombastic Jul 17 '13 at 21:06
  • Well If you need to support browsers that do not support it, you will have to find another technology that can read the files. For those browsers, you might be stuck uploading it. You can only do what the browser allows you to do. – epascarello Jul 17 '13 at 21:11
  • so it's File API really the only one solution? – bombastic Jul 17 '13 at 21:13
  • Maybe this will help: http://stackoverflow.com/questions/6978156/get-base64-encode-file-data-from-input-form – David Hellsing Jul 17 '13 at 21:20
  • @David yep exactly what i need but i also found this http://jsfiddle.net/influenztial/qy7h5/ which extremely what i need, but it saves image into a canvas i would like to get the image from the canavas too, in bas64 :P if you can help me ... – bombastic Jul 17 '13 at 21:22
  • @bradbadbedbread I was just telling you if you need to support browsers that do not support the file api, you are going to have to find another solution for them. That means activeX for IE, maybe flash for devices that support that, or a file upload to the server. There is nothing else that can read the file on the client in JavaScript. – epascarello Jul 18 '13 at 13:15
  • 1
    @epascarello yeah and that was exactly my question, how to support all browsers :D – bombastic Jul 18 '13 at 13:20

8 Answers8

250

function readFile() {
  
  if (!this.files || !this.files[0]) return;
    
  const FR = new FileReader();
    
  FR.addEventListener("load", function(evt) {
    document.querySelector("#img").src         = evt.target.result;
    document.querySelector("#b64").textContent = evt.target.result;
  }); 
    
  FR.readAsDataURL(this.files[0]);
  
}

document.querySelector("#inp").addEventListener("change", readFile);
<input id="inp" type="file">
<p id="b64"></p>
<img id="img" height="150">

(P.S: A base64 encoded image (String) 4/3 the size of the original image data)

Check this answer for multiple images upload.

Browser support: http://caniuse.com/#search=file%20api
More info here: https://developer.mozilla.org/en-US/docs/Web/API/FileReader

Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • 2
    yep thank you, so actually i can see File reader is no fully supported, how can i make the same supporting also old android/iOS devices ? – bombastic Jul 18 '13 at 06:30
  • 2
    are there any other browsers? xD – RicardoE Mar 25 '14 at 23:47
  • That was really neat code for image to base64 conversion.. Can I be able to convert this back into image in javascript? I've used base64 encode decode before, but dont have any idea about image conversions.. – The Coder Feb 11 '15 at 15:01
  • 1
    @TheCoder You can put it right into img src as base64 string, to get image data out of it, use canvas context. – Qwerty May 16 '16 at 01:02
  • 1
    @bombastic I used JS to build both iOS and android app on both platform they worked fine. The iOS is normal and on android, i had needed some native code to get permission to gallery... – Osman Gani Khan Masum Jun 17 '19 at 08:41
  • I didnt get this. How come. `e.target.result;` contains the base64 url. Can anyone explain this. I am a newbie to html/javascript – S Andrew Aug 05 '19 at 07:34
  • @SAndrew `Event.target === this // true` so you can use `this`. `Event.target === FR` is not guaranteed to always yield `true` since we're in an async callback. I used `Event.target` because that way you can transform the above function into an Arrow Function `('load', e => {` and still get the right result. https://developer.mozilla.org/en-US/docs/Web/API/Event/target So Event.target is in this case the `FileReader` instance, and one of it's properties is the `result` object: https://developer.mozilla.org/en-US/docs/Web/API/FileReader/result – Roko C. Buljan Aug 05 '19 at 13:51
38

Exactly what you need:) You can choose callback version or Promise version. Note that promises will work in IE only with Promise polyfill lib.You can put this code once on a page, and this function will appear in all your files.

The loadend event is fired when progress has stopped on the loading of a resource (e.g. after "error", "abort", or "load" have been dispatched)

Callback version

        File.prototype.convertToBase64 = function(callback){
                var reader = new FileReader();
                reader.onloadend = function (e) {
                    callback(e.target.result, e.target.error);
                };   
                reader.readAsDataURL(this);
        };

        $("#asd").on('change',function(){
          var selectedFile = this.files[0];
          selectedFile.convertToBase64(function(base64){
               alert(base64);
          }) 
        });

Promise version

    File.prototype.convertToBase64 = function(){
         return new Promise(function(resolve, reject) {
                var reader = new FileReader();
                reader.onloadend = function (e) {
                    resolve({
                      fileName: this.name,
                      result: e.target.result, 
                      error: e.target.error
                    });
                };   
                reader.readAsDataURL(this);
        }.bind(this)); 
    };

    FileList.prototype.convertAllToBase64 = function(regexp){
      // empty regexp if not set
      regexp = regexp || /.*/;
      //making array from FileList
      var filesArray = Array.prototype.slice.call(this);
      var base64PromisesArray = filesArray.
           filter(function(file){
             return (regexp).test(file.name)
           }).map(function(file){
             return file.convertToBase64();
           });
      return Promise.all(base64PromisesArray);
    };

    $("#asd").on('change',function(){
      //for one file
      var selectedFile = this.files[0];
      selectedFile.convertToBase64().
          then(function(obj){
            alert(obj.result);
          });
      });
      //for all files that have file extention png, jpeg, jpg, gif
      this.files.convertAllToBase64(/\.(png|jpeg|jpg|gif)$/i).then(function(objArray){
            objArray.forEach(function(obj, i){
                  console.log("result[" + obj.fileName + "][" + i + "] = " + obj.result);
            });
      });
    })

html

<input type="file" id="asd" multiple/>
Alex Nikulin
  • 8,194
  • 4
  • 35
  • 37
14
<input type="file" onchange="getBaseUrl()">
function getBaseUrl ()  {
    var file = document.querySelector('input[type=file]')['files'][0];
    var reader = new FileReader();
    var baseString;
    reader.onloadend = function () {
        baseString = reader.result;
        console.log(baseString); 
    };
    reader.readAsDataURL(file);
}
N3K0100183
  • 30
  • 6
Vasyl Petrov
  • 360
  • 2
  • 9
7

It's useful to work with Deferred Object in this case, and return promise:

function readImage(inputElement) {
    var deferred = $.Deferred();

    var files = inputElement.get(0).files;
    if (files && files[0]) {
        var fr= new FileReader();
        fr.onload = function(e) {
            deferred.resolve(e.target.result);
        };
        fr.readAsDataURL( files[0] );
    } else {
        deferred.resolve(undefined);
    }

    return deferred.promise();
}

And above function could be used in this way:

var inputElement = $("input[name=file]");
readImage(inputElement).done(function(base64Data){
    alert(base64Data);
});

Or in your case:

$(input).on('change',function(){
  readImage($(this)).done(function(base64Data){ alert(base64Data); });
});
Vasyl Senko
  • 1,779
  • 20
  • 33
  • i really needed this, i mean the deferred since i am returning the base64 to calling method. I want to know if your solution will work in all browsers ? – Thameem Apr 08 '20 at 11:04
1

Function convert image to base64 using jquery (you can convert to vanila js). Hope it help to you!

Usage: input is your nameId input has file image

<input type="file" id="asd"/>
<button onclick="proccessData()">Submit</button>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>

async function converImageToBase64(inputId) {
  let image = $('#'+inputId)[0]['files']

  if (image && image[0]) {
    const reader = new FileReader();

    return new Promise(resolve => {
      reader.onload = ev => {
        resolve(ev.target.result)
      }
      reader.readAsDataURL(image[0])
    })
  }
}

async function proccessData() {
  const image = await converImageToBase64('asd')
  console.log(image)
}

</script>

Example: converImageToBase64('yourFileInputId')

https://codepen.io/mariohandsome/pen/yLadmVb

Thiên Trần
  • 51
  • 1
  • 7
0

For modern Browsers (no IE support)

Html file input

<style>
.upload-button {
  background-color: grey;
}

.upload-button input{
  display:none;
}
</style>
<label for="upload-photo" class="upload-button">
    Upload file
    <input
     type="file"
     id="upload-photo"
    </input>
</label>

JS

document.getElementById("upload-photo").addEventListener("change", function({target}){
 if (target.files && target.files.length) {
      try {
        const uploadedImageBase64 = await convertFileToBase64(target.files[0]); 
        //do something with above data string 
      } catch() {
        //handle error
      }
    }
})

function convertFileToBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
  });
}
Fez Vrasta
  • 14,110
  • 21
  • 98
  • 160
Nitin Jadhav
  • 6,495
  • 1
  • 46
  • 48
-1

// https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL

/* Simple */
function previewImage( image, preview, string )
{

    var preview     = document.querySelector( preview );
    var fileImage   = image.files[0];

    var reader      = new FileReader();

    reader.addEventListener( "load", function() {

        preview.style.height    = "100";
        preview.title           = fileImage.name;

        // convert image file to base64 string
        preview.src             = reader.result;

        /* --- */

        document.querySelector( string ).value = reader.result;                    

    }, false );

    if ( fileImage )
    {
        reader.readAsDataURL( fileImage );
    }

}

document.querySelector( "#imageID" ).addEventListener( "change", function() {

    previewImage( this, "#imagePreviewID", "#imageStringID" );

} )
/* Simple || */
<form>

    File Upload: <input type="file" id="imageID" /><br />
    Preview: <img src="#" id="imagePreviewID" /><br />    
    String base64: <textarea id="imageStringID" rows="10" cols="50"></textarea>

</form>

codesanbox

antelove
  • 3,216
  • 26
  • 20
-1
  const FR = new FileReader();
    
  FR.addEventListener("load", function(evt) {
    document.querySelector("#img").src         = evt.target.result;
    document.querySelector("#b64").`textContent` = evt.target.result;
  }); 
    
  FR.readAsDataURL(this.files[0]);
  
< img id="inp" src="https://tlc.ca/pricing-tool/images/logo.png">
<p id="b64"></p>
<img id="img" height="150">
  • List item
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 10 '23 at 13:46
  • 1
    You just copied the accepted answer and added stuff without explaining, how is this useful? – tyzion Jun 14 '23 at 10:38