Bagaimana Anda bisa menyandikan string ke Base64 di JavaScript?

810

Saya memiliki skrip PHP yang dapat menyandikan gambar PNG ke string Base64.

Saya ingin melakukan hal yang sama menggunakan JavaScript. Saya tahu cara membuka file, tetapi saya tidak yakin bagaimana melakukan encoding. Saya tidak terbiasa bekerja dengan data biner.

nama pengguna
sumber
2
Inilah cara terbaik untuk base64_encode dan base64_decode menggunakan javascript. Lihat tautan di bawah ini. phpjs.org/functions/base64_encode:358 phpjs.org/functions/base64_decode:357
gautamlakum
di sini adalah plugin jquery lain untuk base64 encode / decode
zahid9i
Periksa microjs: microjs.com/#base64
Vinod Srivastav

Jawaban:

866

Anda dapat menggunakan btoa()dan atob()untuk mengkonversi ke dan dari pengkodean base64.

Tampaknya ada beberapa kebingungan dalam komentar mengenai apa fungsi ini diterima / dikembalikan, jadi ...

  • btoa()menerima "string" di mana setiap karakter mewakili byte 8-bit - jika Anda melewatkan string yang mengandung karakter yang tidak dapat direpresentasikan dalam 8 bit, itu mungkin akan rusak . Ini bukan masalah jika Anda benar-benar memperlakukan string sebagai array byte, tetapi jika Anda mencoba melakukan sesuatu yang lain maka Anda harus menyandikannya terlebih dahulu.

  • atob()mengembalikan "string" di mana setiap karakter mewakili byte 8-bit - yaitu, nilainya akan berada di antara 0dan 0xff. Ini tidak berarti itu ASCII - mungkin jika Anda menggunakan fungsi ini sama sekali, Anda berharap dapat bekerja dengan data biner dan bukan teks.

Lihat juga:

Shog9
sumber
47
Perhatikan bahwa ini juga berfungsi untuk browser webkit, seperti Safari.
Daniel Von Fange
5
tetapi tidak bekerja di iPhone3G dengan iOS 4.1. Itu berfungsi pada iPhone simulator simulator ketika diatur ke iPhone4 atau iPhone.
Grant M
29
Harap perhatikan pertimbangan khusus untuk string Unicode: developer.mozilla.org/En/DOM/Window.btoa#Unicode_Strings btoa dan atob hanya berfungsi dengan baik untuk string berbasis ASCII. Sebagai orang Amerika, Anda mungkin tidak akan melihat perbedaan ... tetapi saat pertama kali Anda menggunakan karakter beraksen, kode Anda akan rusak.
Dan Esparza
70
Anda harus menggunakan btoa(unescape(encodeURIComponent(str))))jika str adalah UFT8
SET
4
Lihat hasil edit saya, @Triynko. Ini tidak dimaksudkan untuk digunakan untuk memproses teks , titik.
Shog9
289

Dari sini :

/**
*
*  Base64 encode / decode
*  http://www.webtoolkit.info/
*
**/
var Base64 = {

// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

// public method for encoding
encode : function (input) {
    var output = "";
    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
    var i = 0;

    input = Base64._utf8_encode(input);

    while (i < input.length) {

        chr1 = input.charCodeAt(i++);
        chr2 = input.charCodeAt(i++);
        chr3 = input.charCodeAt(i++);

        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;

        if (isNaN(chr2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
            enc4 = 64;
        }

        output = output +
        this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
        this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);

    }

    return output;
},

// public method for decoding
decode : function (input) {
    var output = "";
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    while (i < input.length) {

        enc1 = this._keyStr.indexOf(input.charAt(i++));
        enc2 = this._keyStr.indexOf(input.charAt(i++));
        enc3 = this._keyStr.indexOf(input.charAt(i++));
        enc4 = this._keyStr.indexOf(input.charAt(i++));

        chr1 = (enc1 << 2) | (enc2 >> 4);
        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
        chr3 = ((enc3 & 3) << 6) | enc4;

        output = output + String.fromCharCode(chr1);

        if (enc3 != 64) {
            output = output + String.fromCharCode(chr2);
        }
        if (enc4 != 64) {
            output = output + String.fromCharCode(chr3);
        }

    }

    output = Base64._utf8_decode(output);

    return output;

},

// private method for UTF-8 encoding
_utf8_encode : function (string) {
    string = string.replace(/\r\n/g,"\n");
    var utftext = "";

    for (var n = 0; n < string.length; n++) {

        var c = string.charCodeAt(n);

        if (c < 128) {
            utftext += String.fromCharCode(c);
        }
        else if((c > 127) && (c < 2048)) {
            utftext += String.fromCharCode((c >> 6) | 192);
            utftext += String.fromCharCode((c & 63) | 128);
        }
        else {
            utftext += String.fromCharCode((c >> 12) | 224);
            utftext += String.fromCharCode(((c >> 6) & 63) | 128);
            utftext += String.fromCharCode((c & 63) | 128);
        }

    }

    return utftext;
},

// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
    var string = "";
    var i = 0;
    var c = c1 = c2 = 0;

    while ( i < utftext.length ) {

        c = utftext.charCodeAt(i);

        if (c < 128) {
            string += String.fromCharCode(c);
            i++;
        }
        else if((c > 191) && (c < 224)) {
            c2 = utftext.charCodeAt(i+1);
            string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
            i += 2;
        }
        else {
            c2 = utftext.charCodeAt(i+1);
            c3 = utftext.charCodeAt(i+2);
            string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
            i += 3;
        }

    }

    return string;
}

}

Juga, pencarian pada "javascript base64 encoding" ternyata banyak pilihan lain, di atas adalah yang pertama.

Sunny Milenov
sumber
3
Ini juga berguna ketika pengkodean base64 tidak standar; dalam kasus saya karakter "/" tidak digunakan, dan "?" karakter digunakan sebagai gantinya, yang berarti bahkan di Chrome atob () tidak akan men-decode string base64 yang masuk.
Chris Moschini
21
Hati-hati dengan kode ini - ini mencoba untuk menafsirkan string Anda sebagai string yang dikodekan UTF-8. Kami memiliki kasus di mana kami memiliki string biner (yaitu setiap karakter dalam string harus ditafsirkan sebagai byte), dan kode ini memang merusak data. Baca sumbernya, Luke.
Daniel Yankowsky
11
Semua yang diperlukan untuk membuatnya aman bagi sebagian besar pengkodean / dekode biner untuk menghapus string = string.replace(/\r\n/g,"\n");pernyataan yang dipertanyakan dalam metode pengkodean utf8.
Marius
7
@Marius: Saya bertanya-tanya mengapa mereka bahkan mereka sertakan string = string.replace(/\r\n/g,"\n");di tempat pertama, lol. Ini seperti "oh, mari kita enkode string ini, tetapi pertama-tama, mengapa kita tidak menormalisasi semua baris secara acak tanpa alasan yang baik sama sekali". Itu benar-benar harus dikeluarkan dari kelas dalam semua keadaan.
Triynko
2
Saya bukan guru javascript, tetapi kode ini tampaknya mengandung bug: jika chr2 adalah NaN, nilainya masih digunakan dalam pernyataan enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);. Di browser saya ini berfungsi dengan baik,NaN>>4 sama dengan 0, tapi saya tidak tahu apakah semua browser melakukan ini (juga, NaN/16sama dengan NaN).
Jan
117

Internet Explorer 10+

// Define the string
var string = 'Hello World!';

// Encode the String
var encodedString = btoa(string);
console.log(encodedString); // Outputs: "SGVsbG8gV29ybGQh"

// Decode the String
var decodedString = atob(encodedString);
console.log(decodedString); // Outputs: "Hello World!"

Lintas browser

// Create Base64 Object
var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/\r\n/g,"\n");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}}

// Define the string
var string = 'Hello World!';

// Encode the String
var encodedString = Base64.encode(string);
console.log(encodedString); // Outputs: "SGVsbG8gV29ybGQh"

// Decode the String
var decodedString = Base64.decode(encodedString);
console.log(decodedString); // Outputs: "Hello World!"

jsFiddle


dengan Node.js

Inilah cara Anda menyandikan teks normal ke base64 di Node.js:

//Buffer() requires a number, array or string as the first parameter, and an optional encoding type as the second parameter. 
// Default is utf8, possible encoding types are ascii, utf8, ucs2, base64, binary, and hex
var b = new Buffer('JavaScript');
// If we don't use toString(), JavaScript assumes we want to convert the object to utf8.
// We can make it convert to other formats by passing the encoding type to toString().
var s = b.toString('base64');

Dan di sini adalah bagaimana Anda mendekodekan string yang disandikan base64:

var b = new Buffer('SmF2YVNjcmlwdA==', 'base64')
var s = b.toString();

dengan Dojo.js

Untuk menyandikan larik byte menggunakan dojox.encoding.base64:

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

Untuk mendekode string yang disandikan base64:

var bytes = dojox.encoding.base64.decode(str)

bower instal angular-base64

<script src="bower_components/angular-base64/angular-base64.js"></script>

angular
    .module('myApp', ['base64'])
    .controller('myController', [

    '$base64', '$scope', 
    function($base64, $scope) {

        $scope.encoded = $base64.encode('a string');
        $scope.decoded = $base64.decode('YSBzdHJpbmc=');
}]);
davidcondrey
sumber
3
Jawaban ini didasarkan pada kode asli dan TIDAK termasuk pembaruan untuk kode yang diposting di jawaban lain di sini.
Eugene Ryabtsev
Solusi NodeJS yang diajukan sudah tidak digunakan lagi.
Vladimir Nul
94

Kode Sunny sangat bagus kecuali rusak di IE7 karena referensi ke "ini". Diperbaiki dengan mengganti referensi tersebut dengan "Base64":

var Base64 = {
// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

// public method for encoding
encode : function (input) {
    var output = "";
    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
    var i = 0;

    input = Base64._utf8_encode(input);

    while (i < input.length) {

        chr1 = input.charCodeAt(i++);
        chr2 = input.charCodeAt(i++);
        chr3 = input.charCodeAt(i++);

        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;

        if (isNaN(chr2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
            enc4 = 64;
        }

        output = output +
        Base64._keyStr.charAt(enc1) + Base64._keyStr.charAt(enc2) +
        Base64._keyStr.charAt(enc3) + Base64._keyStr.charAt(enc4);

    }

    return output;
},

// public method for decoding
decode : function (input) {
    var output = "";
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    while (i < input.length) {

        enc1 = Base64._keyStr.indexOf(input.charAt(i++));
        enc2 = Base64._keyStr.indexOf(input.charAt(i++));
        enc3 = Base64._keyStr.indexOf(input.charAt(i++));
        enc4 = Base64._keyStr.indexOf(input.charAt(i++));

        chr1 = (enc1 << 2) | (enc2 >> 4);
        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
        chr3 = ((enc3 & 3) << 6) | enc4;

        output = output + String.fromCharCode(chr1);

        if (enc3 != 64) {
            output = output + String.fromCharCode(chr2);
        }
        if (enc4 != 64) {
            output = output + String.fromCharCode(chr3);
        }

    }

    output = Base64._utf8_decode(output);

    return output;

},

// private method for UTF-8 encoding
_utf8_encode : function (string) {
    string = string.replace(/\r\n/g,"\n");
    var utftext = "";

    for (var n = 0; n < string.length; n++) {

        var c = string.charCodeAt(n);

        if (c < 128) {
            utftext += String.fromCharCode(c);
        }
        else if((c > 127) && (c < 2048)) {
            utftext += String.fromCharCode((c >> 6) | 192);
            utftext += String.fromCharCode((c & 63) | 128);
        }
        else {
            utftext += String.fromCharCode((c >> 12) | 224);
            utftext += String.fromCharCode(((c >> 6) & 63) | 128);
            utftext += String.fromCharCode((c & 63) | 128);
        }

    }

    return utftext;
},

// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
    var string = "";
    var i = 0;
    var c = c1 = c2 = 0;

    while ( i < utftext.length ) {

        c = utftext.charCodeAt(i);

        if (c < 128) {
            string += String.fromCharCode(c);
            i++;
        }
        else if((c > 191) && (c < 224)) {
            c2 = utftext.charCodeAt(i+1);
            string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
            i += 2;
        }
        else {
            c2 = utftext.charCodeAt(i+1);
            c3 = utftext.charCodeAt(i+2);
            string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
            i += 3;
        }

    }
    return string;
}
}
pengguna850789
sumber
4
ya salahku, aku mengambil input dari URL browser; dimana | dikonversi ke% 7C; karenanya pengkodean juga salah.
Kanagavelu Sugumar
Saya tahu ini benar-benar tua, tetapi saya telah melihat fungsi ini digunakan di lebih dari satu tempat, string kunci sebenarnya ada di 65 karakter, bukan 64. String itu bukan spek standar, saya tidak yakin itu penting, tapi hanya ingin tahu jika ya?
Jonathan Wagner
"gunakan ketat"; adalah apa yang memecah unsur 'ini' dan jenis lainnya seperti 'dengan' dan dari apa yang telah saya baca, 'eval' mendapat pukulan. Semua ide salah tempat tentang penyalahgunaan. Secara pribadi saya tidak melihat mengapa JavaScript harus melalui rute yang sedang berjalan, itu tidak pernah dimaksudkan untuk menjadi program yang terikat erat dan dibuat lebih kompleks daripada yang sudah ada. Jika Anda ingin terikat maka buatlah kompiler untuk javascript.
Mark Giblin
Saya mencoba menggunakan fungsi ini dan saya menerima kesalahan: Disebabkan oleh: org.mozilla.javascript.EcmaError: TypeError: Tidak dapat menemukan fungsi ganti dalam objek teste teste teste Saya mencoba menyandikan .txt dengan "teste teste teste". Adakah yang tahu mengapa kesalahan ini?
PRVS
@ JonathanWagner - ada 64 karakter yang digunakan untuk penyandian normal. Karakter ke-65 digunakan sebagai bantalan mereka, string input tidak memiliki jumlah karakter yang dapat dibagi oleh 3.
Kickstart
90

Anda dapat menggunakan btoa(ke basis-64) dan atob(dari basis-64).

Untuk IE 9 dan di bawah, coba plugin jquery-base64 :

$.base64.encode("this is a test");
$.base64.decode("dGhpcyBpcyBhIHRlc3Q=");
Vitalii Fedorenko
sumber
133
Mengapa semuanya perlu menjadi plugin jQuery: c ini hanya fungsionalitas inti JavaScript ini tidak ada hubungannya dengan DOM atau jQuery
EaterOfCode
38
Ini bukan fungsi inti atau tidak akan ada banyak jawaban dengan suara berbeda yang berbeda (termasuk kode do-it-yourself; dr). Jadi, imho ini sebenarnya kasus penggunaan yang baik untuk jQuery (satu liner, diharapkan bekerja bahkan di WebView Android) - bahkan lebih jika sudah menjadi ketergantungan.
Risadinha
1
Saya suka memasang cuplikan kode seperti ini ke jQuery terutama karena mereka akan ada di namespace yang terkontrol. Jika Anda tidak menggunakan AMD atau CommonJS atau pola desain yang serupa, mudah bagi namespace global Anda untuk menjadi benar-benar berantakan dengan banyak fungsi acak.
sffc
9
@Risadinha - kecuali fungsinya tidak bergantung pada atau memperluas apa pun jQuery sama sekali ... secara harfiah satu-satunya referensi ke jQuery dalam kodenya melampirkannya ke objek jQuery ... jadi apa gunanya melampirkannya ke jQuery dan karenanya memerlukan jQuery untuk digunakan? Buat saja itu sendiri 1 liner base64.encode(...)dan base64.decode(...)... melampirkannya ke jQuery ketika tidak memiliki fungsi spesifik jQuery sama sekali tidak masuk akal ...
Jimbo Jonny
1
jQuery tidak diminta. Bukan jawaban yang valid untuk pertanyaan JS biasa.
metaColin
34

Dari komentar (oleh SET dan Stefan Steiger) di bawah jawaban yang diterima, berikut adalah ringkasan singkat tentang cara menyandikan / mendekode string ke / dari base64 tanpa perlu perpustakaan.

str = "The quick brown fox jumps over the lazy dog";
b64 = btoa(unescape(encodeURIComponent(str)));
str = decodeURIComponent(escape(window.atob(b64)));

Demo

(menggunakan perpustakaan jQuery, tetapi tidak untuk encode / decode)

crashwap
sumber
Untuk mengonfirmasi, ini mendukung karakter UTF-8?
Crashalot
1
@ Crashalot Saya menyadari ini terlambat dua tahun, tapi ya benar. Saya juga baru menyadari ketika saya mengetik ini bahwa Anda memberikan suntingan yang mungkin membuat UTF8 berfungsi.
tycrek
Bagi siapa pun di sini mencari solusi yang baik untuk digunakan dengan Node.js, saya dapat mengkonfirmasi ini berfungsi. Untuk decoding di Node, saya menggunakan:Buffer.from(b64data, 'base64').toString();
tycrek
26

Ada beberapa bug di kedua implementasi _utf8_decode. c1dan c2ditugaskan sebagai variabel global karena rusaknya penggunaan varpernyataan, dan c3tidak diinisialisasi atau dideklarasikan sama sekali.

Ini berfungsi, tetapi variabel-variabel ini akan menimpa yang sudah ada dengan nama yang sama di luar fungsi ini.

Inilah versi yang tidak akan melakukan ini:

// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
    var string = "";
    var i = 0;
    var c = 0, c1 = 0, c2 = 0;

    while ( i < utftext.length ) {

        c = utftext.charCodeAt(i);

        if (c < 128) {
            string += String.fromCharCode(c);
            i++;
        }
        else if((c > 191) && (c < 224)) {
            c1 = utftext.charCodeAt(i+1);
            string += String.fromCharCode(((c & 31) << 6) | (c1 & 63));
            i += 2;
        }
        else {
            c1 = utftext.charCodeAt(i+1);
            c2 = utftext.charCodeAt(i+2);
            string += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63));
            i += 3;
        }

    }
    return string;
}
Robbles
sumber
9
@ Kan saya tidak punya rep yang cukup untuk mengedit jawaban ketika saya menulis jawaban ini ... pada 2011.
robbles
2
IE7? Saya kira kita harus berhenti membuang waktu untuk menulis kode untuk itu, orang tidak akan berhenti menggunakan teknologi lama ini kecuali kita pengembang memaksanya!
Rami Dabain
@RonanDejhero tidak berfungsi di IE7? Saya tidak ingat apakah saya menguji di browser tertentu.
Robbles
1
Apa yang saya maksudkan jika tidak bekerja di IE7, tidak ada yang peduli !. saya tidak menguji dan tidak akan mengujinya :)
Rami Dabain
16

Saya memberi jawaban pada Sunny, tetapi saya ingin menyumbang kembali beberapa perubahan yang saya buat untuk proyek saya sendiri kalau-kalau ada orang yang menganggapnya berguna. Pada dasarnya saya baru saja membersihkan kode asli sedikit sehingga JSLint tidak banyak mengeluh, dan saya membuat metode yang ditandai sebagai pribadi dalam komentar sebenarnya pribadi. Saya juga menambahkan dua metode yang saya butuhkan dalam proyek saya sendiri, yaitu decodeToHexdan encodeFromHex.

Kode:

var Base64 = (function() {
    "use strict";

    var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    var _utf8_encode = function (string) {

        var utftext = "", c, n;

        string = string.replace(/\r\n/g,"\n");

        for (n = 0; n < string.length; n++) {

            c = string.charCodeAt(n);

            if (c < 128) {

                utftext += String.fromCharCode(c);

            } else if((c > 127) && (c < 2048)) {

                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);

            } else {

                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);

            }

        }

        return utftext;
    };

    var _utf8_decode = function (utftext) {
        var string = "", i = 0, c = 0, c1 = 0, c2 = 0;

        while ( i < utftext.length ) {

            c = utftext.charCodeAt(i);

            if (c < 128) {

                string += String.fromCharCode(c);
                i++;

            } else if((c > 191) && (c < 224)) {

                c1 = utftext.charCodeAt(i+1);
                string += String.fromCharCode(((c & 31) << 6) | (c1 & 63));
                i += 2;

            } else {

                c1 = utftext.charCodeAt(i+1);
                c2 = utftext.charCodeAt(i+2);
                string += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63));
                i += 3;

            }

        }

        return string;
    };

    var _hexEncode = function(input) {
        var output = '', i;

        for(i = 0; i < input.length; i++) {
            output += input.charCodeAt(i).toString(16);
        }

        return output;
    };

    var _hexDecode = function(input) {
        var output = '', i;

        if(input.length % 2 > 0) {
            input = '0' + input;
        }

        for(i = 0; i < input.length; i = i + 2) {
            output += String.fromCharCode(parseInt(input.charAt(i) + input.charAt(i + 1), 16));
        }

        return output;
    };

    var encode = function (input) {
        var output = "", chr1, chr2, chr3, enc1, enc2, enc3, enc4, i = 0;

        input = _utf8_encode(input);

        while (i < input.length) {

            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);

            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;

            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }

            output += _keyStr.charAt(enc1);
            output += _keyStr.charAt(enc2);
            output += _keyStr.charAt(enc3);
            output += _keyStr.charAt(enc4);

        }

        return output;
    };

    var decode = function (input) {
        var output = "", chr1, chr2, chr3, enc1, enc2, enc3, enc4, i = 0;

        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

        while (i < input.length) {

            enc1 = _keyStr.indexOf(input.charAt(i++));
            enc2 = _keyStr.indexOf(input.charAt(i++));
            enc3 = _keyStr.indexOf(input.charAt(i++));
            enc4 = _keyStr.indexOf(input.charAt(i++));

            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;

            output += String.fromCharCode(chr1);

            if (enc3 !== 64) {
                output += String.fromCharCode(chr2);
            }
            if (enc4 !== 64) {
                output += String.fromCharCode(chr3);
            }

        }

        return _utf8_decode(output);
    };

    var decodeToHex = function(input) {
        return _hexEncode(decode(input));
    };

    var encodeFromHex = function(input) {
        return encode(_hexDecode(input));
    };

    return {
        'encode': encode,
        'decode': decode,
        'decodeToHex': decodeToHex,
        'encodeFromHex': encodeFromHex
    };
}());
Joe Dyndale
sumber
Awalnya saya pikir Anda membuka gulungan keluaran menjadi pernyataan terpisah akan lebih optimal, tetapi setelah saya memikirkannya sebentar, ini seharusnya lebih tidak efisien karena string Javascript tidak dapat diubah dan akan menyebabkan 4 salinan gumpalan data yang berpotensi besar ketika bekerja dengan file data biner besar. Ini adalah taruhan yang lebih aman untuk menggabungkan 4 karakter bersama pertama dan kemudian membangun string baru. Saya berharap saya tahu pasti metode membangun string yang lebih baik yang pasti akan efisien pada semua platform. (Bahkan IE6)
Marius
Saya belum mempertimbangkan kinerja dalam pembersihan kode yang semula diposting. Saya hanya membuatnya lebih mudah dibaca dan membuat metode yang ditandai sebagai pribadi dalam komentar di aslinya sebenarnya bersifat pribadi dengan menggunakan pola modul pengungkapan. Saya yakin itu dapat dioptimalkan dalam hal kinerja juga. Tidak yakin kapan pengumpulan sampah akan muncul di sini, dan hashing file besar melalui Javascript tidak terlalu umum (atau memang kemungkinan bukan solusi optimal dalam hal apa pun).
Joe Dyndale
Lucu bagaimana kode ini hidup di sini. Sudah ada 3 versi berbeda di halaman ini.
gregn3
16

Untuk browser yang lebih baru untuk menyandikan Uint8Array ke string, dan mendekode string ke Uint8Array.

const base64 = {
    decode: s => Uint8Array.from(atob(s), c => c.charCodeAt(0)),
    encode: b => btoa(String.fromCharCode(...new Uint8Array(b)))
};

Untuk Node.js Anda dapat menggunakan yang berikut ini untuk menyandikan string, Buffer, atau Uint8Array ke string, dan mendekode dari string, Buffer, atau Uint8Array ke Buffer.

const base64 = {
    decode: s => Buffer.from(s, 'base64'),
    encode: b => Buffer.from(b).toString('base64')
};
Rix
sumber
13

Untuk membuat String64 yang dikodekan Base64 friendly, di JavaScript Anda bisa melakukan sesuatu seperti ini:

// if this is your Base64 encoded string
var str = 'VGhpcyBpcyBhbiBhd2Vzb21lIHNjcmlwdA=='; 

// make URL friendly:
str = str.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, '');

// reverse to original encoding
str = (str + '===').slice(0, str.length + (str.length % 4));
str = str.replace(/-/g, '+').replace(/_/g, '/');

Lihat juga Fiddle ini: http://jsfiddle.net/magikMaker/7bjaT/

pembuat magik
sumber
9
Saya dengan rendah hati akan menyarankan bahwa penggunaan encodeURIComponentdapat menghasilkan hasil yang unggul dengan pengeluaran usaha yang lebih sedikit dari pihak pengembang.
Pablo Fernandez
11
encodeURIComponent akan mengubah panjang string yang disandikan base64, dan mengganti '-' dan '_' dengan '+' dan '/' adalah praktik standar saat menggunakan base64 dalam URL (mis. docs.python.org/library/base64.html#base64 .urlsafe_b64encode ). Tidak perlu kesal.
natevw
12

Harap dicatat bahwa ini tidak cocok untuk string Unicode mentah! Lihat bagian Unicode di sini .

Sintaks untuk penyandian

var encodedData = window.btoa(stringToEncode);

Sintaks untuk decoding

var decodedData = window.atob(encodedData);

Kathir
sumber
1
Tautan langsung ke bagian unicode: developer.mozilla.org/en-US/docs/Web/API/…
TomTasche
12

Saya telah menulis ulang dengan tangan, metode encoding dan decoding ini dengan pengecualian hexadecimal menjadi format modular untuk kompatibilitas lintas platform / browser dan juga dengan pelingkupan privat nyata, dan penggunaan btoadanatob jika ada karena kecepatan daripada menggunakan encoding sendiri:

https://gist.github.com/Nijikokun/5192472

Pemakaian:

base64.encode(/* String */);
base64.decode(/* String */);

utf8.encode(/* String */);
utf8.decode(/* String */);
Nijikokun
sumber
12

Pertanyaan ini dan jawabannya mengarahkan saya ke arah yang benar.
Terutama dengan unicode atob dan btoa tidak dapat digunakan "vanilla" dan hari ini SEMUA adalah unicode ..

Langsung dari Mozilla, dua fungsi yang bagus untuk tujuan ini (diuji dengan tag unicode dan html di dalamnya)

function b64EncodeUnicode(str) {
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
        return String.fromCharCode('0x' + p1);
    }));
}

b64EncodeUnicode('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU="
b64EncodeUnicode('\n'); // "Cg=="



function b64DecodeUnicode(str) {
    return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
}

b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"
b64DecodeUnicode('Cg=='); // "\n"

Fungsi-fungsi ini akan melakukan kilat cepat dibandingkan dengan decoding base64 baku menggunakan fungsi javascript kustom karena btoa dan atob dieksekusi di luar interpreter.

Jika Anda dapat mengabaikan IE lama dan ponsel lama (seperti iphone 3?) Ini harus menjadi solusi yang baik.

John
sumber
10

jika Anda perlu menyandikan objek gambar HTML, Anda dapat menulis fungsi sederhana seperti:

function getBase64Image(img) {  
  var canvas = document.createElement("canvas");  
  canvas.width = img.width;  
  canvas.height = img.height;  
  var ctx = canvas.getContext("2d");  
  ctx.drawImage(img, 0, 0);  
  var dataURL = canvas.toDataURL("image/png");  
  // escape data:image prefix
  return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");  
  // or just return dataURL
  // return dataURL
}  

Untuk mendapatkan base64 gambar dengan id:

function getBase64ImageById(id){  
  return getBase64Image(document.getElementById(id));  
} 

lebih lanjut di sini

Nedudi
sumber
Yap, dan var img = Gambar baru (); img.src = "../images/myPic.png";
pdschuller
7

Berkontribusi dengan polyfill yang diperkecil untuk window.atob+ window.btoayang saat ini saya gunakan.

(function(){function t(t){this.message=t}var e="undefined"!=typeof exports?exports:this,r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";t.prototype=Error(),t.prototype.name="InvalidCharacterError",e.btoa||(e.btoa=function(e){for(var o,n,a=0,i=r,c="";e.charAt(0|a)||(i="=",a%1);c+=i.charAt(63&o>>8-8*(a%1))){if(n=e.charCodeAt(a+=.75),n>255)throw new t("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");o=o<<8|n}return c}),e.atob||(e.atob=function(e){if(e=e.replace(/=+$/,""),1==e.length%4)throw new t("'atob' failed: The string to be decoded is not correctly encoded.");for(var o,n,a=0,i=0,c="";n=e.charAt(i++);~n&&(o=a%4?64*o+n:n,a++%4)?c+=String.fromCharCode(255&o>>(6&-2*a)):0)n=r.indexOf(n);return c})})();
Johan
sumber
6

Saya lebih suka menggunakan metode encode / decode bas64 dari CryptoJS , perpustakaan paling populer untuk algoritma kriptografi standar dan aman yang diterapkan dalam JavaScript menggunakan praktik dan pola terbaik.

Dan Dascalescu
sumber
6

Ini adalah versi pabrik AngularJS dari @ user850789:

'use strict';

var ProjectNameBase64Factory = angular.module('project_name.factories.base64', []);

ProjectNameBase64Factory.factory('Base64', function () {
    var Base64 = {
        // private property
        _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

        // public method for encoding
        encode: function (input) {
            var output = "";
            var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
            var i = 0;

            input = Base64._utf8_encode(input);

            while (i < input.length) {

                chr1 = input.charCodeAt(i++);
                chr2 = input.charCodeAt(i++);
                chr3 = input.charCodeAt(i++);

                enc1 = chr1 >> 2;
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                enc4 = chr3 & 63;

                if (isNaN(chr2)) {
                    enc3 = enc4 = 64;
                } else if (isNaN(chr3)) {
                    enc4 = 64;
                }

                output = output +
                         Base64._keyStr.charAt(enc1) + Base64._keyStr.charAt(enc2) +
                         Base64._keyStr.charAt(enc3) + Base64._keyStr.charAt(enc4);

            }

            return output;
        },

        // public method for decoding
        decode: function (input) {
            var output = "";
            var chr1, chr2, chr3;
            var enc1, enc2, enc3, enc4;
            var i = 0;

            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

            while (i < input.length) {

                enc1 = Base64._keyStr.indexOf(input.charAt(i++));
                enc2 = Base64._keyStr.indexOf(input.charAt(i++));
                enc3 = Base64._keyStr.indexOf(input.charAt(i++));
                enc4 = Base64._keyStr.indexOf(input.charAt(i++));

                chr1 = (enc1 << 2) | (enc2 >> 4);
                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                chr3 = ((enc3 & 3) << 6) | enc4;

                output = output + String.fromCharCode(chr1);

                if (enc3 != 64) {
                    output = output + String.fromCharCode(chr2);
                }
                if (enc4 != 64) {
                    output = output + String.fromCharCode(chr3);
                }

            }

            output = Base64._utf8_decode(output);

            return output;

        },

        // private method for UTF-8 encoding
        _utf8_encode: function (string) {
            string = string.replace(/\r\n/g, "\n");
            var utftext = "";

            for (var n = 0; n < string.length; n++) {

                var c = string.charCodeAt(n);

                if (c < 128) {
                    utftext += String.fromCharCode(c);
                }
                else if ((c > 127) && (c < 2048)) {
                    utftext += String.fromCharCode((c >> 6) | 192);
                    utftext += String.fromCharCode((c & 63) | 128);
                }
                else {
                    utftext += String.fromCharCode((c >> 12) | 224);
                    utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                    utftext += String.fromCharCode((c & 63) | 128);
                }

            }

            return utftext;
        },

        // private method for UTF-8 decoding
        _utf8_decode: function (utftext) {
            var string = "";
            var i = 0;
            var c = 0, c2 = 0, c3 = 0;

            while (i < utftext.length) {

                c = utftext.charCodeAt(i);

                if (c < 128) {
                    string += String.fromCharCode(c);
                    i++;
                }
                else if ((c > 191) && (c < 224)) {
                    c2 = utftext.charCodeAt(i + 1);
                    string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                    i += 2;
                }
                else {
                    c2 = utftext.charCodeAt(i + 1);
                    c3 = utftext.charCodeAt(i + 2);
                    string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                    i += 3;
                }

            }
            return string;
        }
    };
    return Base64;
});
DI
sumber
6

Saya perlu pengkodean string UTF-8 sebagai base64 untuk proyek saya. Sebagian besar jawaban di sini tampaknya tidak menangani pasangan pengganti UTF-16 dengan benar ketika dikonversi ke UTF-8 jadi, demi penyelesaian, saya akan memposting solusi saya:

function strToUTF8Base64(str) {

    function decodeSurrogatePair(hi, lo) {
        var resultChar = 0x010000;
        resultChar += lo - 0xDC00;
        resultChar += (hi - 0xD800) << 10;
        return resultChar;
    }

    var bytes = [0, 0, 0];
    var byteIndex = 0;
    var result = [];

    function output(s) {
        result.push(s);
    }

    function emitBase64() {

        var digits =
                'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
                'abcdefghijklmnopqrstuvwxyz' +
                '0123456789+/';

        function toDigit(value) {
            return digits[value];
        }

        // --Byte 0--    --Byte 1--    --Byte 2--
        // 1111  1122    2222  3333    3344  4444

        var d1 = toDigit(bytes[0] >> 2);
        var d2 = toDigit(
            ((bytes[0] & 0x03) << 4) |
            (bytes[1] >> 4));
        var d3 = toDigit(
            ((bytes[1] & 0x0F) << 2) |
            (bytes[2] >> 6));
        var d4 = toDigit(
            bytes[2] & 0x3F);

        if (byteIndex === 1) {
            output(d1 + d2 + '==');
        }
        else if (byteIndex === 2) {
            output(d1 + d2 + d3 + '=');
        }
        else {
            output(d1 + d2 + d3 + d4);
        }
    }

    function emit(chr) {
        bytes[byteIndex++] = chr;
        if (byteIndex == 3) {
            emitBase64();
            bytes[0] = 0;
            bytes[1] = 0;
            bytes[2] = 0;
            byteIndex = 0;
        }
    }

    function emitLast() {
        if (byteIndex > 0) {
            emitBase64();
        }
    }

    // Converts the string to UTF8:

    var i, chr;
    var hi, lo;
    for (i = 0; i < str.length; i++) {
        chr = str.charCodeAt(i);

        // Test and decode surrogate pairs in the string
        if (chr >= 0xD800 && chr <= 0xDBFF) {
            hi = chr;
            lo = str.charCodeAt(i + 1);
            if (lo >= 0xDC00 && lo <= 0xDFFF) {
                chr = decodeSurrogatePair(hi, lo);
                i++;
            }
        }

        // Encode the character as UTF-8.
        if (chr < 0x80) {
            emit(chr);
        }
        else if (chr < 0x0800) {
            emit((chr >> 6) | 0xC0);
            emit(((chr >> 0) & 0x3F) | 0x80);
        }
        else if (chr < 0x10000) {
            emit((chr >> 12) | 0xE0);
            emit(((chr >>  6) & 0x3F) | 0x80);
            emit(((chr >>  0) & 0x3F) | 0x80);
        }
        else if (chr < 0x110000) {
            emit((chr >> 18) | 0xF0);
            emit(((chr >> 12) & 0x3F) | 0x80);
            emit(((chr >>  6) & 0x3F) | 0x80);
            emit(((chr >>  0) & 0x3F) | 0x80);
        }
    }

    emitLast();

    return result.join('');
}

Perhatikan bahwa kode ini tidak diuji secara menyeluruh. Saya menguji beberapa input, termasuk hal-hal seperti strToUTF8Base64('衠衢蠩蠨')dan dibandingkan dengan output alat encoding online ( https://www.base64encode.org/ ).

Ricardo Machado
sumber
5

Untuk proyek saya, saya masih perlu mendukung IE7 dan bekerja dengan input besar untuk menyandikan.

Berdasarkan kode yang diusulkan oleh Joe Dyndale dan seperti yang disarankan dalam komentar oleh Marius, adalah mungkin untuk meningkatkan kinerja dengan IE7 dengan membangun hasilnya dengan array bukan string.

Berikut ini contoh untuk penyandian:

var encode = function (input) {
    var output = [], chr1, chr2, chr3, enc1, enc2, enc3, enc4, i = 0;

    input = _utf8_encode(input);

    while (i < input.length) {

        chr1 = input.charCodeAt(i++);
        chr2 = input.charCodeAt(i++);
        chr3 = input.charCodeAt(i++);

        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;

        if (isNaN(chr2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
            enc4 = 64;
        }

        output.push(_keyStr.charAt(enc1));
        output.push(_keyStr.charAt(enc2));
        output.push(_keyStr.charAt(enc3));
        output.push(_keyStr.charAt(enc4));

    }

    return output.join("");
};
Nico
sumber
5

Meskipun sedikit lebih banyak pekerjaan, jika Anda menginginkan solusi asli berkinerja tinggi, ada beberapa fungsi HTML5 yang dapat Anda gunakan.

Jika Anda dapat memasukkan data ke dalam Blob, maka Anda dapat menggunakan fungsi FileReader.readAsDataURL () untuk mendapatkan data://URL dan memotong bagian depannya untuk mendapatkan data base64.

Anda mungkin harus melakukan pemrosesan lebih lanjut untuk urldecode data, karena saya tidak yakin apakah +karakter lolos atau tidak untuk data://URL, tetapi ini seharusnya cukup sepele.

Malvine
sumber
5

Nah, jika Anda menggunakan dojo, 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 mendekode string yang disandikan base64:

var bytes = dojox.encoding.base64.decode(str);
Vikash Pandey
sumber
3

Anda dapat menggunakan window.btoadan window.atob...

const encoded = window.btoa('Alireza Dezfoolian'); // encode a string
const decoded = window.atob(encoded); // decode the string

Mungkin menggunakan cara MDN dapat melakukan pekerjaan Anda dengan sebaik-baiknya ... Juga menerima unicode ... menggunakan dua fungsi sederhana ini:

// ucs-2 string to base64 encoded ascii
function utoa(str) {
    return window.btoa(unescape(encodeURIComponent(str)));
}
// base64 encoded ascii to ucs-2 string
function atou(str) {
    return decodeURIComponent(escape(window.atob(str)));
}
// Usage:
utoa('✓ à la mode'); // 4pyTIMOgIGxhIG1vZGU=
atou('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"

utoa('I \u2661 Unicode!'); // SSDimaEgVW5pY29kZSE=
atou('SSDimaEgVW5pY29kZSE='); // "I ♡ Unicode!"
Alireza
sumber
3

Berikut ini adalah DEMO LANGSUNG dari atob()dan btoa()JS dibangun pada fungsi:

<!DOCTYPE html>
<html>
  <head>
    <style>
      textarea{
        width:30%;
        height:100px;
      }
    </style>
    <script>
      // encode string to base64
      function encode()
      {
        var txt = document.getElementById("txt1").value;
        var result = btoa(txt);
        document.getElementById("txt2").value = result;
      }
      // decode base64 back to original string
      function decode()
      {
        var txt = document.getElementById("txt3").value;
        var result = atob(txt);
        document.getElementById("txt4").value = result;
      }
    </script>
  </head>
  <body>
    <div>
      <textarea id="txt1">Some text to decode
      </textarea>
    </div>
    <div>
      <input type="button" id="btnencode" value="Encode" onClick="encode()"/>
    </div>
    <div>
      <textarea id="txt2">
      </textarea>
    </div>
    <br/>
    <div>
      <textarea id="txt3">U29tZSB0ZXh0IHRvIGRlY29kZQ==
      </textarea>
    </div>
    <div>
      <input type="button" id="btndecode" value="Decode" onClick="decode()"/>
    </div>
    <div>
      <textarea id="txt4">
      </textarea>
    </div>
  </body>
</html>
Jonathana
sumber
2

Gunakan perpustakaan js-base64 sebagai

btoa () tidak berfungsi dengan emoji

var str = "I was funny 😂";
console.log("Original string:", str);

var encodedStr = Base64.encode(str)
console.log("Encoded string:", encodedStr);

var decodedStr = Base64.decode(encodedStr)
console.log("Decoded string:", decodedStr);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/base64.min.js"></script>

Shivaji Mutkule
sumber