Bagaimana saya bisa mengubah gambar menjadi string Base64 menggunakan JavaScript?

Jawaban:

182

Anda dapat menggunakan HTML5 <canvas>untuk itu:

Buat kanvas, muat gambar Anda ke dalamnya dan kemudian gunakan toDataURL()untuk mendapatkan representasi Base64 (sebenarnya, itu adalah data:URL, tetapi berisi gambar yang disandikan Base64).

Pencuri
sumber
3
Apakah toDataURLmemberikan kontrol atas callback seperti done/fail/alwayshalnya untuk xhr?
Jeroen
Bisakah kita mengekstrak 2 atau lebih kanvas sebagai satu PNG?
techie_28
141
Bisakah Anda membuat jsbin atau setidaknya menulis beberapa kode di sini?
vsync
9
Pendekatan ini gagal dalam kasus pelanggaran CORS. Terlepas dari itu, solusi ini harus menjawab pertanyaan itu.
Revanth Kumar
Ini adalah paket npm untuk itu
user3517175
852

Ada beberapa pendekatan yang dapat Anda pilih:

1. Pendekatan: FileReader

Muat gambar sebagai gumpalan melalui XMLHttpRequest dan gunakan FileReader API untuk mengubahnya menjadi 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)
})

Contoh kode ini juga dapat diimplementasikan menggunakan WHATWG fetch API :

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

Pendekatan-pendekatan ini:

  • kurangnya dukungan browser
  • memiliki kompresi yang lebih baik
  • bekerja untuk jenis file lain juga

Dukungan Browser:


2. Pendekatan: Kanvas

Masukkan gambar ke dalam Image-Object, cat ke kanvas yang tidak dicat dan ubah kembali kanvas menjadi 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)
  }
)

Secara terperinci

Format input yang didukung:

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

Format output yang didukung:

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

Dukungan Browser:


3. Pendekatan: Gambar dari sistem file lokal

Jika Anda ingin mengonversi gambar dari sistem file pengguna, Anda perlu mengambil pendekatan yang berbeda. Gunakan 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
sumber
56
Tidak bekerja di chrome untuk saya: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
Kalau-kalau ini membuat orang lain tersandung, rutin ini menyertakan header "data: image / jpg; base64," di string yang dikembalikannya, jadi Anda tidak perlu menambahkannya.
Chris Rae
1
Warnin2: sesuatu mengacaukan konten. di suatu tempat di sepanjang jalan, ada kemungkinan data rusak / diubah (walaupun, mungkin tidak banyak), setidaknya itu terjadi pada saya di firefox 35 pada beberapa gambar, base64 berbeda dari base64 yang dibuat php pada saat yang sama gambar.
hanshenrik
1
Ya itu benar. Beberapa data mungkin hilang karena kita benar-benar menggambar gambar ke elemen kanvas ( developer.mozilla.org/en-US/docs/Web/API/… ) dan kemudian mengonversinya menjadi dataURL ( developer.mozilla.org/en- US / docs / Web / API / HTMLCanvasElement / ... ).
HaNdTriX
1
Pendekatan: FileReader (2) bekerja lebih cepat daripada mendekati Canvas. Diuji pada foto besar. Semoga ini akan bermanfaat bagi seseorang.
Maks
83

Cuplikan ini dapat mengonversi file string, gambar, dan bahkan video Anda menjadi data string 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
sumber
3
Tidak hanya hebat, ini juga mem-bypass masalah crossdomain! Dengan ini, Anda dapat memungkinkan pengguna untuk memasok gambar mereka sendiri atau gambar dari URL (karena Windows akan mengambilnya sendiri), menggambar mereka di atas kanvas, dan bekerja dengan mereka sambil masih dapat menggunakan .toDataURL () dll. Terima kasih banyak!
ElDoRado1239
Halo, bagaimana ini dapat diterapkan pada gambar yang diambil dari url jarak jauh tanpa menghadapi masalah lintas domain? Terima kasih
guthik
Ini kadang-kadang berfungsi di Chrome 78.0.3904.97, tetapi di lain waktu tab tersebut macet.
Dshiz
28

Pada dasarnya, jika gambar Anda

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

maka Anda dapat mengubahnya seperti

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
sumber
5
Sayangnya ini hanya akan berfungsi untuk gambar lokal, jika Anda mencoba menggunakan gambar jarak jauh (pilih satu dari web) itu menulis ini ke konsol (firefox): 'SecurityError: Operasi tidak aman'.
user2677034
1
Ini dapat bekerja pada gambar lain tetapi tergantung pada pengaturan CORS dari situs itu dan harus ditentukan sebagai<img id='Img1' src='someurl' crossorigin='anonymous'>
Mike
Di Firefox Anda dapat menonaktifkan keamanan itu untuk sementara. Masuk "tentang: konfigurasi" dan ubah properti "privacy.file_unique_origin" ke false
Manuel Romeiro
21

Inilah yang saya lakukan:

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

Dan inilah cara Anda menggunakannya

base64( $('input[type="file"]'), function(data){
  console.log(data.base64)
})
James Harrington
sumber
7
apa itu btoa? :)
Alexander Mills
4
a = ASCII dan b = Binary stackoverflow.com/questions/33854103/…
James Harrington
14

Saya menemukan bahwa cara paling aman dan dapat diandalkan untuk melakukannya adalah menggunakan FileReader().

Demo: Gambar ke 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
sumber
6

Jika Anda memiliki objek file, fungsi sederhana ini akan berfungsi:

function getBase64 (file, callback) {

    const reader = new FileReader();

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

    reader.readAsDataURL(file);
}

Contoh penggunaan:

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
sumber
5

Anda bisa menggunakan FileAPI , tetapi itu tidak banyak didukung.

Artem Tikhomirov
sumber
4

Sejauh yang saya tahu, gambar dapat dikonversi menjadi string Base64 baik oleh FileReader () atau menyimpannya di elemen kanvas dan kemudian menggunakan toDataURL () untuk mendapatkan gambar. Saya punya masalah serupa yang bisa Anda rujuk.

Konversi gambar ke kanvas yang sudah dimuat

Ajeet Lakhani
sumber
4

Coba kode ini:

Untuk acara perubahan unggahan file, panggil fungsi ini:

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

Menyimpan data Base64 dalam arsip tersembunyi untuk digunakan.

ravi polara
sumber
1
Hai Ravi! Saya melihat Anda relatif baru. Kecuali poster asli secara khusus meminta solusi pustaka seperti jQuery, lodash dan sebagainya, lebih baik bagi semua orang untuk menjawab menggunakan minimum, dalam hal ini, javascript biasa. Jika Anda masih ingin berkontribusi dengan jQuery, harap jelaskan dalam entri Anda :)
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
sumber
0

Nah, jika Anda menggunakan Dojo Toolkit , itu memberi kami cara langsung untuk menyandikan atau mendekode ke Base64.

Coba ini:

Untuk menyandikan larik byte menggunakan dojox.encoding.base64:

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

Untuk memecahkan kode string yang disandikan Base64:

var bytes = dojox.encoding.base64.decode(str);
Vikash Pandey
sumber
2
@DownVoter - Dear lebih baik untuk menunjukkan kesalahan juga jika Anda menandai sesuatu yang negatif. sehingga seseorang dapat meningkat. sejauh yang saya mengerti dojo juga di perpustakaan JavaScript maka jika Anda diizinkan untuk menggunakan dojo, Anda pasti dapat menggunakan pendekatan ini.
Vikash Pandey