Conversión de imagen a Base64

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

Me gustaría obtener la imagen en base64 una vez que el usuario eligió eso (antes de enviar el formulario)

Algo como :

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

Leí sobre File API y otras cosas, me gustaría una solución simple y entre navegadores (IE6 / IE7 excluido obviamente)

Cualquier ayuda agradecida gracias.

rimbombante
fuente
1
¿Y qué no entendiste sobre la API de archivos HTML5? ¿Qué intentaste? ¿Lo que no funcionó?
epascarello
@epascarello no son totalmente compatibles en realidad caniuse.com/#feat=fileapi necesito una solución , especialmente porque las versiones de Android todavía se usan (versiones antiguas), así como para las versiones antiguas de iOS, y también me gustaría involucrar a IE9 que todavía se usa mucho: P
grandilocuente
una solución para qué? ¿Qué intentas hacer con el archivo? base64file()- ¿Eso es un complemento?
David Hellsing
@David solo me gustaría obtener el archivo base64 una vez que el usuario seleccione el archivo de su pc, base64file () es solo un ejemplo
grandilocuente
1
@epascarello sí, y esa fue exactamente mi pregunta, cómo admitir todos los navegadores: D
grandilocuente

Respuestas:

210

function readFile() {
  
  if (this.files && this.files[0]) {
    
    var FR= new FileReader();
    
    FR.addEventListener("load", function(e) {
      document.getElementById("img").src       = e.target.result;
      document.getElementById("b64").innerHTML = e.target.result;
    }); 
    
    FR.readAsDataURL( this.files[0] );
  }
  
}

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

( PS: una imagen codificada en base64 (cadena) 4/3 del tamaño de los datos de la imagen original)

Compruebe esta respuesta para cargar varias imágenes .

Soporte del navegador: http://caniuse.com/#search=file%20api
Más información aquí: https://developer.mozilla.org/en-US/docs/Web/API/FileReader

Roko C. Buljan
fuente
2
Sí, gracias, entonces puedo ver que el lector de archivos no es totalmente compatible, ¿cómo puedo hacer que el mismo soporte también sea compatible con dispositivos Android / iOS antiguos?
grandilocuente
1
¿hay otros navegadores? xD
RicardoE
Ese fue un código realmente bueno para la conversión de imagen a base64. ¿Puedo convertir esto de nuevo en una imagen en javascript? He usado la decodificación de codificación base64 antes, pero no tengo idea sobre conversiones de imágenes ..
The Coder
@TheCoder Puede ponerlo directamente en img src como cadena base64, para obtener datos de imagen, use el contexto del lienzo.
Qwerty
1
@bombastic Usé JS para crear aplicaciones de iOS y Android en ambas plataformas, funcionaron bien. El iOS es normal y en Android, necesitaba un código nativo para obtener permiso para la galería ...
Osman Gani Khan Masum
36

Exactamente lo que necesita :) Puede elegir la versión de devolución de llamada o la versión Promise. Tenga en cuenta que las promesas funcionarán en IE solo con Promise polyfill lib. Puede colocar este código una vez en una página, y esta función aparecerá en todos sus archivos.

El evento loadend se activa cuando el progreso se ha detenido en la carga de un recurso (por ejemplo, después de que se hayan enviado "error", "abortar" o "cargar")

Versión de devolución de llamada

        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);
          }) 
        });

Versión de promesa

    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
fuente
8
<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);
}
Vasyl Petrov
fuente
1
'file' se declara pero su valor nunca se lee dentro de la función getBaseUrl ().
Biranchi
@Biranchi filese usa en la última líneareader.readAsDataURL(file);
Achim
7

Es útil trabajar con Objeto diferido en este caso y devolver la promesa:

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();
}

Y la función anterior podría usarse de esta manera:

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

O en tu caso:

$(input).on('change',function(){
  readImage($(this)).done(function(base64Data){ alert(base64Data); });
});
Vasyl Senko
fuente
Realmente necesitaba esto, me refiero al diferido ya que estoy devolviendo la base64 al método de llamada. Quiero saber si su solución funcionará en todos los navegadores.
Thameem