Comment puis-je convertir une image en chaîne Base64 en utilisant JavaScript?

Réponses:

182

Vous pouvez utiliser le HTML5 <canvas>pour cela:

Créez un canevas, chargez-y votre image puis utilisez-la toDataURL()pour obtenir la représentation Base64 (en fait, c'est une data:URL, mais elle contient l'image encodée Base64).

ThiefMaster
la source
3
Donne le toDataURLcontrôle des rappels done/fail/alwayscomme c'est le cas pour xhr?
Jeroen
Peut-on extraire 2 toiles ou plus en un seul PNG?
techie_28
141
Pouvez-vous faire un jsbin ou au moins écrire du code ici?
vsync
9
Cette approche échoue en cas de violation de CORS. En dehors de cela, cette solution devrait répondre à la question.
Revanth Kumar
Voici le paquet npm pour lui
user3517175
853

Il existe plusieurs approches parmi lesquelles vous pouvez choisir:

1. Approche: FileReader

Chargez l'image en tant qu'objet blob via XMLHttpRequest et utilisez l' API FileReader pour la convertir 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)
})

Cet exemple de code peut également être implémenté à l'aide de l' API de récupération 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)
  })

Ces approches:

  • manque de prise en charge du navigateur
  • avoir une meilleure compression
  • fonctionne également pour d'autres types de fichiers

Prise en charge du navigateur:


2. Approche: toile

Chargez l'image dans un objet image, peignez-la sur un canevas non contaminé et reconvertissez le canevas en 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 détail

Formats d'entrée pris en charge:

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

Formats de sortie pris en charge:

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

Prise en charge du navigateur:


3. Approche: images du système de fichiers local

Si vous souhaitez convertir des images à partir du système de fichiers des utilisateurs, vous devez adopter une approche différente. Utilisez l' 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
la source
56
Ne fonctionne pas dans le chrome pour moi: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
5
Juste au cas où cela déclencherait quelqu'un d'autre, cette routine inclut l'en-tête "data: image / jpg; base64" dans la chaîne qu'elle renvoie, vous n'avez donc pas besoin d'ajouter cela.
Chris Rae
1
Warnin2: quelque chose perturbe le contenu. quelque part en cours de route, il y a une chance que les données soient corrompues / altérées (même si, peut-être pas beaucoup), du moins cela se produit pour moi sur firefox 35 sur certaines images, la base64 est différente de la base64 que php crée sur le même image.
hanshenrik
1
Oui, c'est correcte. Certaines données peuvent être perdues car nous dessinons réellement l'image sur un élément canvas ( developer.mozilla.org/en-US/docs/Web/API/… ), puis la convertissons en dataURL ( developer.mozilla.org/en- US / docs / Web / API / HTMLCanvasElement /… ).
HaNdTriX
1
Approche: FileReader (2) fonctionne plus rapidement que l'approche Canvas. Testé sur de grandes photos. J'espère que ce sera utile pour quelqu'un.
Max
83

Cet extrait peut convertir votre chaîne, image et même fichier vidéo en données de chaîne 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
la source
3
Non seulement c'est génial, cela contourne également le problème d'origine du domaine croisé! Avec cela, vous pouvez autoriser les utilisateurs à fournir leurs propres images ou images à partir d'une URL (puisque Windows les récupérera de leur propre chef), les dessiner sur le canevas et travailler avec eux tout en pouvant utiliser .toDataURL () etc. Merci beaucoup!
ElDoRado1239
Bonjour, comment cela peut-il être appliqué à une image chargée à partir d'une URL distante sans rencontrer de problèmes interdomaines? Merci
guthik
Cela fonctionne parfois dans Chrome 78.0.3904.97, mais d'autres fois, il bloque l'onglet.
Dshiz
28

Fondamentalement, si votre image est

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

alors vous pouvez le convertir comme

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
la source
5
Malheureusement, cela ne fonctionnera que pour les images locales, si vous l'essayez en utilisant une image distante (choisissez-en une sur le Web), cela écrit sur la console (firefox): 'SecurityError: L'opération n'est pas sécurisée'.
user2677034
1
Cela peut fonctionner sur d'autres images mais dépend des paramètres CORS de ce site et doit être spécifié comme<img id='Img1' src='someurl' crossorigin='anonymous'>
Mike
Sur Firefox, vous pouvez désactiver temporairement cette sécurité. Passez à "about: config" et changez la propriété "privacy.file_unique_origin" en false
Manuel Romeiro
21

Voici ce que j'ai fait:

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

Et voici comment vous l'utilisez

base64( $('input[type="file"]'), function(data){
  console.log(data.base64)
})
James Harrington
la source
7
qu'est-ce que btoa? :)
Alexander Mills
4
a = ASCII et b = stackoverflow.com/questions
James Harrington
14

J'ai trouvé que la façon la plus sûre et la plus fiable de le faire est de l'utiliser FileReader().

Démo: Image vers 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
la source
6

Si vous avez un objet fichier, cette fonction simple fonctionnera:

function getBase64 (file, callback) {

    const reader = new FileReader();

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

    reader.readAsDataURL(file);
}

Exemple d'utilisation:

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
la source
5

Vous pouvez utiliser FileAPI , mais il n'est pratiquement pas pris en charge.

Artem Tikhomirov
la source
4

Pour autant que je sache, une image peut être convertie en une chaîne Base64 soit par FileReader () soit en la stockant dans l'élément canvas, puis en utilisant toDataURL () pour obtenir l'image. J'ai eu le même genre de problème que vous pouvez vous référer.

Convertir une image en toile déjà chargée

Ajeet Lakhani
la source
4

Essayez ce code:

Pour un événement de modification de téléchargement de fichier, appelez cette fonction:

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

Stockez les données Base64 dans des fichiers cachés à utiliser.

ravi polara
la source
1
Salut Ravi! Je vois que vous êtes relativement nouveau. À moins que l'affiche originale ne demande spécifiquement une solution de bibliothèque telle que jQuery, lodash et ainsi de suite, il est préférable que tout le monde réponde en utilisant le strict minimum, dans ce cas, du javascript simple. Si vous souhaitez toujours contribuer avec jQuery, veuillez le préciser clairement dans votre entrée :)
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
la source
0

Eh bien, si vous utilisez Dojo Toolkit , cela nous donne un moyen direct d'encoder ou de décoder en Base64.

Essaye ça:

Pour coder un tableau d'octets à l'aide de dojox.encoding.base64:

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

Pour décoder une chaîne codée en Base64:

var bytes = dojox.encoding.base64.decode(str);
Vikash Pandey
la source
2
@DownVoter - Cher, il vaut mieux signaler l'erreur aussi si vous marquez quelque chose de négatif. afin que quelqu'un puisse s'améliorer. dans la mesure où je comprends dojo dans une bibliothèque JavaScript, alors si vous êtes autorisé à utiliser dojo, vous pouvez certainement utiliser cette approche.
Vikash Pandey