¿Cómo puedo convertir una imagen en una cadena Base64 usando JavaScript?

Respuestas:

182

Puedes usar el HTML5 <canvas>para ello:

Cree un lienzo, cargue su imagen en él y luego úselo toDataURL()para obtener la representación de Base64 (en realidad, es una data:URL, pero contiene la imagen codificada en Base64).

ThiefMaster
fuente
3
¿ Da toDataURLcontrol sobre las devoluciones de llamada, done/fail/alwayscomo es el caso de xhr?
Jeroen
¿Podemos extraer 2 o más lienzos como un solo PNG?
techie_28
141
¿Puedes hacer un jsbin o al menos escribir un código aquí?
vsync el
99
Este enfoque falla en el caso de violación de CORS. Aparte de eso, esta solución debería abordar la cuestión.
Revanth Kumar
Aquí está el paquete npm para él
user3517175
853

Hay varios enfoques entre los que puede elegir:

1. Enfoque: FileReader

Cargue la imagen como blob a través de XMLHttpRequest y use la API FileReader para convertirla en dataURL :

function toDataURL(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.onload = function() {
    var reader = new FileReader();
    reader.onloadend = function() {
      callback(reader.result);
    }
    reader.readAsDataURL(xhr.response);
  };
  xhr.open('GET', url);
  xhr.responseType = 'blob';
  xhr.send();
}

toDataURL('https://www.gravatar.com/avatar/d50c83cc0c6523b4d3f6085295c953e0', function(dataUrl) {
  console.log('RESULT:', dataUrl)
})

Este ejemplo de código también podría implementarse utilizando la API de recuperación WHATWG :

const toDataURL = url => fetch(url)
  .then(response => response.blob())
  .then(blob => new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onloadend = () => resolve(reader.result)
    reader.onerror = reject
    reader.readAsDataURL(blob)
  }))


toDataURL('https://www.gravatar.com/avatar/d50c83cc0c6523b4d3f6085295c953e0')
  .then(dataUrl => {
    console.log('RESULT:', dataUrl)
  })

Estos enfoques:

  • falta en el soporte del navegador
  • tener una mejor compresión
  • trabajar para otros tipos de archivos también

Soporte de navegador:


2. Enfoque: lienzo

Cargue la imagen en un Objeto de imagen, pinte en un lienzo no contaminado y vuelva a convertir el lienzo en un dataURL.

function toDataURL(src, callback, outputFormat) {
  var img = new Image();
  img.crossOrigin = 'Anonymous';
  img.onload = function() {
    var canvas = document.createElement('CANVAS');
    var ctx = canvas.getContext('2d');
    var dataURL;
    canvas.height = this.naturalHeight;
    canvas.width = this.naturalWidth;
    ctx.drawImage(this, 0, 0);
    dataURL = canvas.toDataURL(outputFormat);
    callback(dataURL);
  };
  img.src = src;
  if (img.complete || img.complete === undefined) {
    img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
    img.src = src;
  }
}

toDataURL(
  'https://www.gravatar.com/avatar/d50c83cc0c6523b4d3f6085295c953e0',
  function(dataUrl) {
    console.log('RESULT:', dataUrl)
  }
)

En detalle

Formatos de entrada admitidos:

image/png, image/jpeg, image/jpg, image/gif, image/bmp, image/tiff, image/x-icon, image/svg+xml, image/webp,image/xxx

Formatos de salida admitidos:

image/png, image/jpeg, image/webp(Cromo)

Soporte de navegador:


3. Enfoque: imágenes del sistema de archivos local

Si desea convertir imágenes del sistema de archivos de los usuarios, debe adoptar un enfoque diferente. Use la API FileReader :

function encodeImageFileAsURL(element) {
  var file = element.files[0];
  var reader = new FileReader();
  reader.onloadend = function() {
    console.log('RESULT', reader.result)
  }
  reader.readAsDataURL(file);
}
<input type="file" onchange="encodeImageFileAsURL(this)" />

HaNdTriX
fuente
56
No funciona en Chrome para mí:Image from origin **** has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://fiddle.jshell.net' is therefore not allowed access.
DickieBoy 05 de
55
En caso de que esto haga tropezar a alguien más, esta rutina incluye el encabezado "data: image / jpg; base64" en la cadena que devuelve, por lo que no necesita agregar eso.
Chris Rae
1
Warnin2: algo interfiere con el contenido. En algún lugar del camino, existe la posibilidad de que los datos se corrompan / alteren (aunque, tal vez no mucho), al menos eso me sucede en Firefox 35 en algunas imágenes, la base64 es diferente de la base64 que php crea en la misma imagen.
hanshenrik
1
Si, eso es correcto. Algunos datos pueden perderse ya que en realidad dibujamos la imagen en un elemento de lienzo ( developer.mozilla.org/en-US/docs/Web/API/… ) y luego la convertimos en dataURL ( developer.mozilla.org/en- US / docs / Web / API / HTMLCanvasElement / ... ).
HaNdTriX
1
Enfoque: FileReader (2) funciona más rápido que el enfoque Canvas. Probado en fotos grandes. Espero que sea útil para alguien.
Max
83

Este fragmento puede convertir su cadena, imagen e incluso archivo de video a datos de cadena Base64.

<input id="inputFileToLoad" type="file" onchange="encodeImageFileAsURL();" />
<div id="imgTest"></div>
<script type='text/javascript'>
  function encodeImageFileAsURL() {

    var filesSelected = document.getElementById("inputFileToLoad").files;
    if (filesSelected.length > 0) {
      var fileToLoad = filesSelected[0];

      var fileReader = new FileReader();

      fileReader.onload = function(fileLoadedEvent) {
        var srcData = fileLoadedEvent.target.result; // <--- data: base64

        var newImage = document.createElement('img');
        newImage.src = srcData;

        document.getElementById("imgTest").innerHTML = newImage.outerHTML;
        alert("Converted Base64 version is " + document.getElementById("imgTest").innerHTML);
        console.log("Converted Base64 version is " + document.getElementById("imgTest").innerHTML);
      }
      fileReader.readAsDataURL(fileToLoad);
    }
  }
</script>

Carles Alcolea
fuente
3
¡No solo es genial, sino que también evita el problema de origen de dominios cruzados! Con esto, puede permitir que los usuarios proporcionen sus propias imágenes o imágenes desde una URL (ya que Windows las buscará por sí mismas), dibujarlas en el lienzo y trabajar con ellas sin dejar de poder usar .toDataURL () etc. ¡Muchas gracias!
ElDoRado1239
Hola, ¿cómo se puede aplicar esto a una imagen cargada desde una URL remota sin enfrentar problemas de dominio cruzado? Gracias
guthik
Esto funciona a veces en Chrome 78.0.3904.97, pero otras veces bloquea la pestaña.
Dshiz
28

Básicamente, si tu imagen es

<img id='Img1' src='someurl'>

entonces puedes convertirlo como

var c = document.createElement('canvas');
var img = document.getElementById('Img1');
c.height = img.naturalHeight;
c.width = img.naturalWidth;
var ctx = c.getContext('2d');

ctx.drawImage(img, 0, 0, c.width, c.height);
var base64String = c.toDataURL();
mehmet mecek
fuente
55
Desafortunadamente, esto solo funcionará para imágenes locales, si lo intentas usando una imagen remota (elige una de la web) escribe esto en la consola (firefox): 'SecurityError: la operación es insegura'.
user2677034
1
Puede funcionar en otras imágenes, pero depende de la configuración CORS de ese sitio y debe especificarse como<img id='Img1' src='someurl' crossorigin='anonymous'>
Mike
En Firefox puede deshabilitar temporalmente esa seguridad. Ir a "about: config" y cambiar la propiedad "privacy.file_unique_origin" a false
Manuel Romeiro
21

Aquí esta lo que hice:

// Author James Harrington 2014
function base64(file, callback){
  var coolFile = {};
  function readerOnload(e){
    var base64 = btoa(e.target.result);
    coolFile.base64 = base64;
    callback(coolFile)
  };

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

  var file = file[0].files[0];
  coolFile.filetype = file.type;
  coolFile.size = file.size;
  coolFile.filename = file.name;
  reader.readAsBinaryString(file);
}

Y así es como lo usas

base64( $('input[type="file"]'), function(data){
  console.log(data.base64)
})
James Harrington
fuente
77
que es btoa :)
Alexander Mills
44
a = ASCII yb = Binary stackoverflow.com/questions/33854103/…
James Harrington
14

Descubrí que la forma más segura y confiable de hacerlo es usarlo FileReader().

Demostración: imagen a Base64

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
  </head>
  <body>
    <input id="myinput" type="file" onchange="encode();" />
    <div id="dummy">
    </div>
    <div>
      <textarea style="width:100%;height:500px;" id="txt">
      </textarea>
    </div>
    <script>
      function encode() {
        var selectedfile = document.getElementById("myinput").files;
        if (selectedfile.length > 0) {
          var imageFile = selectedfile[0];
          var fileReader = new FileReader();
          fileReader.onload = function(fileLoadedEvent) {
            var srcData = fileLoadedEvent.target.result;
            var newImage = document.createElement('img');
            newImage.src = srcData;
            document.getElementById("dummy").innerHTML = newImage.outerHTML;
            document.getElementById("txt").value = document.getElementById("dummy").innerHTML;
          }
          fileReader.readAsDataURL(imageFile);
        }
      }
    </script>
  </body>
</html>
jonathana
fuente
6

Si tiene un objeto de archivo, esta simple función funcionará:

function getBase64 (file, callback) {

    const reader = new FileReader();

    reader.addEventListener('load', () => callback(reader.result));

    reader.readAsDataURL(file);
}

Ejemplo de uso:

getBase64(fileObjectFromInput, function(base64Data){
    console.log("Base64 of file is", base64Data); // Here you can have your code which uses Base64 for its operation, // file to Base64 by oneshubh
});
Shubham
fuente
5

Podrías usar FileAPI , pero no es compatible.

Artem Tikhomirov
fuente
4

Hasta donde sé, una imagen se puede convertir en una cadena Base64, ya sea por FileReader () o almacenarla en el elemento de lienzo y luego usar toDataURL () para obtener la imagen. Tuve el mismo tipo de problema, puedes referir esto.

Convierta una imagen a lienzo que ya está cargada

Ajeet Lakhani
fuente
4

Prueba este código:

Para un evento de cambio de carga de archivo, llame a esta función:

$("#fileproof").on('change', function () {
    readImage($(this)).done(function (base64Data) { $('#<%=hfimgbs64.ClientID%>').val(base64Data); });
});

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

Almacene datos Base64 en archivos ocultos para su uso.

ravi polara
fuente
1
Hola ravi Veo que eres relativamente nuevo. A menos que el póster original solicite específicamente una solución de biblioteca como jQuery, lodash, etc., es mejor que todos respondan utilizando los mínimos, en este caso, javascript simple. Si todavía desea contribuir con jQuery, por favor, déjelo bien claro en su entrada :)
Carles Alcolea
3
uploadProfile(e) {

    let file = e.target.files[0];
    let reader = new FileReader();

    reader.onloadend = function() {
        console.log('RESULT', reader.result)
    }
    reader.readAsDataURL(file);
}
Mahedi Hasan Durjoy
fuente
0

Bueno, si está utilizando Dojo Toolkit , nos brinda una forma directa de codificar o decodificar en Base64.

Prueba esto:

Para codificar una matriz de bytes usando dojox.encoding.base64:

var str = dojox.encoding.base64.encode(myByteArray);

Para decodificar una cadena codificada en Base64:

var bytes = dojox.encoding.base64.decode(str);
Vikash Pandey
fuente
2
@DownVoter - Estimado, es mejor señalar el error también si está marcando algo negativo. para que alguien pueda mejorar. por lo que yo entiendo dojo en una biblioteca de JavaScript, entonces si puedes usar dojo, definitivamente puedes usar este enfoque.
Vikash Pandey