Jika Anda memiliki UTF8, gunakan ini (sebenarnya berfungsi dengan sumber SVG), seperti:
btoa(unescape(encodeURIComponent(str)))
contoh:
var imgsrc = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(markup)));
var img = new Image(1, 1); // width, height values are optional params
img.src = imgsrc;
Jika Anda perlu memecahkan kode base64 itu, gunakan ini:
var str2 = decodeURIComponent(escape(window.atob(b64)));
console.log(str2);
Contoh:
var str = "äöüÄÖÜçéèñ";
var b64 = window.btoa(unescape(encodeURIComponent(str)))
console.log(b64);
var str2 = decodeURIComponent(escape(window.atob(b64)));
console.log(str2);
Catatan: jika Anda perlu membuatnya bekerja di mobile-safari, Anda mungkin perlu menghapus semua ruang putih dari data base64 ...
function b64_to_utf8( str ) {
str = str.replace(/\s/g, '');
return decodeURIComponent(escape(window.atob( str )));
}
Pembaruan 2017
Masalah ini telah menggangguku lagi.
Kebenaran sederhananya adalah, atob tidak benar-benar menangani string UTF8 - hanya ASCII.
Juga, saya tidak akan menggunakan bloatware seperti js-base64.
Tetapi webtoolkit memiliki implementasi yang kecil, bagus, dan sangat dapat dipertahankan:
/**
*
* 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);
} // Whend
return output;
} // End Function encode
// 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);
}
} // Whend
output = Base64._utf8_decode(output);
return output;
} // End Function decode
// private method for UTF-8 encoding
,_utf8_encode: function (string)
{
var utftext = "";
string = string.replace(/\r\n/g, "\n");
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);
}
} // Next n
return utftext;
} // End Function _utf8_encode
// private method for UTF-8 decoding
,_utf8_decode: function (utftext)
{
var string = "";
var i = 0;
var c, c1, c2, c3;
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;
}
} // Whend
return string;
} // End Function _utf8_decode
}
https://www.fileformat.info/info/unicode/utf8.htm
Untuk setiap karakter yang sama dengan atau di bawah 127 (hex 0x7F), representasi UTF-8 adalah satu byte. Ini hanya 7 bit terendah dari nilai unicode penuh. Ini juga sama dengan nilai ASCII.
Untuk karakter yang sama atau di bawah 2047 (hex 0x07FF), representasi UTF-8 tersebar di dua byte. Byte pertama akan memiliki dua bit tinggi yang ditetapkan dan bit ketiga jelas (yaitu 0xC2 ke 0xDF). Byte kedua akan memiliki set bit atas dan bit kedua jelas (yaitu 0x80 ke 0xBF).
Untuk semua karakter yang sama atau lebih besar dari 2048 tetapi kurang dari 65535 (0xFFFF), representasi UTF-8 tersebar di tiga byte.
escape
konversi string dalam satu yang hanya berisi karakter yang valid url. Itu mencegah kesalahan.escape
danunescape
yang usang dalam JavaScript 1.5 dan satu harus menggunakanencodeURIComponent
ataudecodeURIComponent
, masing-masing, sebagai gantinya. Anda menggunakan fungsi yang usang dan baru secara bersamaan. Mengapa? Lihat: w3schools.com/jsref/jsref_escape.aspMenggunakan
btoa
denganunescape
danencodeURIComponent
tidak bekerja untuk saya. Mengganti semua karakter khusus dengan entitas XML / HTML dan kemudian mengonversi ke representasi base64 adalah satu-satunya cara untuk mengatasi masalah ini bagi saya. Beberapa kode:sumber
Blob
objek untuk menangani konversi.Blob
dapat menangani data biner apa pun.Gunakan perpustakaan sebagai gantinya
Kami tidak harus menemukan kembali roda. Cukup gunakan perpustakaan untuk menghemat waktu dan sakit kepala.
js-base64
https://github.com/dankogai/js-base64 bagus dan saya mengonfirmasi itu mendukung unicode dengan sangat baik.
sumber
Saya hanya berpikir saya harus berbagi bagaimana saya benar-benar menyelesaikan masalah dan mengapa saya pikir ini adalah solusi yang tepat (asalkan Anda tidak mengoptimalkan browser lama).
Konversi data ke dataURL (
data: ...
)Mengizinkan pengguna menyimpan data
Terlepas dari solusi yang jelas - membuka jendela baru dengan dataURL Anda sebagai URL, Anda dapat melakukan dua hal lainnya.
1. Gunakan fileSaver.js
Penghemat file dapat membuat dialog Hemat file yang sebenarnya dengan nama file yang telah ditentukan. Itu juga dapat mundur ke pendekatan dataURL normal.
2. Gunakan (percobaan)
URL.createObjectURL
Ini bagus untuk menggunakan kembali data yang disandikan base64. Itu menciptakan URL pendek untuk data AndaURL:
Jangan lupa untuk menggunakan URL termasuk
blob
awalan terkemuka . Saya menggunakandocument.body
lagi:Anda dapat menggunakan URL pendek ini sebagai target AJAX,
<script>
sumber atau<a>
lokasi href. Anda bertanggung jawab untuk menghancurkan URL:sumber
Sebagai pelengkap jawaban Stefan Steiger: (karena tidak terlihat bagus sebagai komentar)
Memperluas prototipe String:
Pemakaian:
CATATAN:
Sebagaimana dinyatakan dalam komentar, penggunaan
unescape
tidak disarankan karena dapat dihapus di masa depan:sumber
unescape
akan segera dihentikan sesuai MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…btoa () hanya mendukung karakter dari String.fromCodePoint (0) hingga String.fromCodePoint (255). Untuk karakter Base64 dengan titik kode 256 atau lebih tinggi Anda harus menyandikan / mendekodekan ini sebelum dan sesudah.
Dan pada titik ini menjadi rumit ...
Setiap tanda yang mungkin diatur dalam Tabel Unicode. Unicode-Table dibagi dalam berbagai bidang (bahasa, simbol matematika, dan sebagainya ...). Setiap tanda pada pesawat memiliki nomor titik kode yang unik. Secara teoritis, jumlahnya bisa menjadi besar secara sewenang-wenang.
Komputer menyimpan data dalam byte (8 bit, 0x00 heksadesimal - 0xff, biner 00000000 - 11111111, desimal 0 - 255). Rentang ini biasanya digunakan untuk menyimpan karakter dasar (rentang Latin1).
Untuk karakter dengan titik kode lebih tinggi maka 255 ada pengkodean yang berbeda. JavaScript menggunakan 16 bit per sign (UTF-16), string yang disebut DOMString. Unicode dapat menangani poin kode hingga 0x10fffff. Itu berarti, bahwa suatu metode harus ada untuk menyimpan beberapa bit dari beberapa sel.
String.fromCodePoint(0x10000).length == 2
UTF-16 menggunakan pasangan pengganti untuk menyimpan 20 bit dalam dua sel 16bit. Pengganti yang lebih tinggi pertama dimulai dengan 110110xxxxxxxxxx , yang kedua lebih rendah dengan 110111xxxxxxxxxx . Unicode memesan pesawat sendiri untuk ini: https://unicode-table.com/de/#high-surrogates
Untuk menyimpan karakter dalam byte (kisaran Latin1) prosedur standar menggunakan UTF-8 .
Maaf untuk mengatakan itu, tapi saya pikir tidak ada cara lain untuk mengimplementasikan fungsi ini sendiri.
bagaimana cara menggunakannya:
decodeBase64(encodeBase64("\u{1F604}"))
demo: https://jsfiddle.net/qrLadeb8/
sumber
stringToUTF8
danutf8ToString
meskipunSaya sendiri mengalami masalah ini.
Pertama, sedikit modifikasi kode Anda:
Kemudian gunakan inspektur web favorit Anda, letakkan breakpoint pada baris kode yang menetapkan this.loader.src, kemudian jalankan kode ini:
Bergantung pada aplikasi Anda, mengganti karakter yang di luar jangkauan mungkin atau mungkin tidak berfungsi, karena Anda akan memodifikasi data. Lihat catatan di MDN tentang karakter unicode dengan metode btoa:
https://developer.mozilla.org/en-US/docs/Web/API/window.btoa
sumber