Wenn Sie UTF8 haben, verwenden Sie dies (funktioniert tatsächlich mit SVG-Quelle) wie:
btoa(unescape(encodeURIComponent(str)))
Beispiel:
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;
Wenn Sie diese base64 dekodieren müssen, verwenden Sie Folgendes:
var str2 = decodeURIComponent(escape(window.atob(b64)));
console.log(str2);
Beispiel:
var str = "äöüÄÖÜçéèñ";
var b64 = window.btoa(unescape(encodeURIComponent(str)))
console.log(b64);
var str2 = decodeURIComponent(escape(window.atob(b64)));
console.log(str2);
Hinweis: Wenn dies in Mobile-Safari funktionieren soll, müssen Sie möglicherweise den gesamten Leerraum aus den base64-Daten entfernen ...
function b64_to_utf8( str ) {
str = str.replace(/\s/g, '');
return decodeURIComponent(escape(window.atob( str )));
}
Update 2017
Dieses Problem hat mich wieder nervt.
Die einfache Wahrheit ist, dass atob nicht wirklich mit UTF8-Strings umgeht - es ist nur ASCII.
Außerdem würde ich keine Bloatware wie js-base64 verwenden.
Aber webtoolkit hat eine kleine, nette und sehr wartbare Implementierung:
/**
*
* 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
Für jedes Zeichen gleich oder unter 127 (hex 0x7F) ist die UTF-8-Darstellung ein Byte. Es sind nur die niedrigsten 7 Bits des vollständigen Unicode-Werts. Dies entspricht auch dem ASCII-Wert.
Bei Zeichen gleich oder unter 2047 (hex 0x07FF) ist die UTF-8-Darstellung auf zwei Bytes verteilt. Im ersten Byte werden die beiden hohen Bits gesetzt und das dritte Bit gelöscht (dh 0xC2 bis 0xDF). Im zweiten Byte wird das oberste Bit gesetzt und das zweite Bit gelöscht (dh 0x80 bis 0xBF).
Für alle Zeichen gleich oder größer als 2048, jedoch kleiner als 65535 (0xFFFF) ist die UTF-8-Darstellung auf drei Bytes verteilt.
escape
konvertiert eine Zeichenfolge in eine Zeichenfolge, die nur URL-gültige Zeichen enthält. Das verhindert die Fehler.escape
undunescape
wurden in JavaScript 1.5 veraltet und sollte man verwendenencodeURIComponent
oderdecodeURIComponent
jeweils statt. Sie verwenden die veralteten und neuen Funktionen zusammen. Warum? Sehen: w3schools.com/jsref/jsref_escape.aspVerwenden
btoa
mitunescape
undencodeURIComponent
hat bei mir nicht funktioniert. Das Ersetzen aller Sonderzeichen durch XML / HTML-Entitäten und das anschließende Konvertieren in die base64-Darstellung war für mich die einzige Möglichkeit, dieses Problem zu lösen. Etwas Code:quelle
Blob
object, um die Konvertierung durchzuführen.Blob
kann mit beliebigen Binärdaten umgehen.Verwenden Sie stattdessen eine Bibliothek
Wir müssen das Rad nicht neu erfinden. Verwenden Sie einfach eine Bibliothek, um Zeit und Kopfschmerzen zu sparen.
js-base64
https://github.com/dankogai/js-base64 ist gut und ich bestätige, dass es Unicode sehr gut unterstützt.
quelle
Ich dachte nur, ich sollte mitteilen, wie ich das Problem tatsächlich gelöst habe und warum ich denke, dass dies das Richtige ist Lösung ist (vorausgesetzt, Sie optimieren nicht für alte Browser).
Konvertieren von Daten in dataURL (
data: ...
)Benutzer können Daten speichern
Abgesehen von der offensichtlichen Lösung - das Öffnen eines neuen Fensters mit Ihrer dataURL als URL - können Sie zwei weitere Dinge tun.
1. Verwenden Sie fileSaver.js
File Saver kann einen tatsächlichen fileSave-Dialog mit einem vordefinierten Dateinamen erstellen. Es kann auch auf den normalen dataURL-Ansatz zurückgreifen.
2. Verwenden Sie (experimentell)
URL.createObjectURL
Dies ist ideal für die Wiederverwendung von Base64-codierten Daten. Es wird eine kurze URL für Ihre dataURL erstellt:
Vergessen Sie nicht, die URL einschließlich des führenden
blob
Präfixes zu verwenden. Ich habedocument.body
wieder verwendet:Sie können diese kurze URL als AJAX-Ziel,
<script>
Quelle oder<a>
href-Speicherort verwenden. Sie sind jedoch dafür verantwortlich, die URL zu zerstören:quelle
Als Ergänzung zu Stefan Steiger Antwort: (da es als Kommentar nicht gut aussieht)
String-Prototyp erweitern:
Verwendung:
HINWEIS:
Wie in den Kommentaren angegeben, wird die Verwendung
unescape
nicht empfohlen, da sie möglicherweise in Zukunft entfernt wird:quelle
unescape
wird bald veraltet sein gemäß MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…btoa () unterstützt nur Zeichen von String.fromCodePoint (0) bis String.fromCodePoint (255). Für Base64-Zeichen mit einem Codepunkt 256 oder höher müssen Sie diese vorher und nachher codieren / decodieren.
Und an diesem Punkt wird es schwierig ...
Jedes mögliche Zeichen ist in einer Unicode-Tabelle angeordnet. Die Unicode-Tabelle ist in verschiedene Ebenen unterteilt (Sprachen, mathematische Symbole usw.). Jedes Zeichen in einem Flugzeug hat eine eindeutige Codepunktnummer. Theoretisch kann die Anzahl beliebig groß werden.
Ein Computer speichert die Daten in Bytes (8 Bit, hexadezimal 0x00 - 0xff, binär 00000000 - 11111111, dezimal 0 - 255). Dieser Bereich wird normalerweise zum Speichern von Basiszeichen verwendet (Bereich Latin1).
Für Zeichen mit höherem Codepunkt als 255 existieren unterschiedliche Codierungen. JavaScript verwendet 16 Bit pro Zeichen (UTF-16), die Zeichenfolge mit dem Namen DOMString. Unicode kann Codepunkte bis zu 0x10fffff verarbeiten. Das bedeutet, dass eine Methode vorhanden sein muss, um mehrere Bits über mehrere Zellen hinweg zu speichern.
String.fromCodePoint(0x10000).length == 2
UTF-16 verwendet Ersatzpaare, um 20 Bit in zwei 16-Bit-Zellen zu speichern. Der erste höhere Ersatz beginnt mit 110110xxxxxxxxxx , der niedrigere zweite mit 110111xxxxxxxxxx . Unicode reservierte dafür eigene Flugzeuge: https://unicode-table.com/de/#high-surrogates
Verwenden Sie UTF-8, um Zeichen in standardisierten Bytes (Bereich Latin1) zu speichern .
Tut mir leid, das zu sagen, aber ich denke, es gibt keine andere Möglichkeit, diese Funktion selbst zu implementieren.
wie man es benutzt:
decodeBase64(encodeBase64("\u{1F604}"))
Demo: https://jsfiddle.net/qrLadeb8/
quelle
stringToUTF8
undutf8ToString
obwohlIch bin gerade selbst auf dieses Problem gestoßen.
Ändern Sie zunächst Ihren Code geringfügig:
Verwenden Sie dann Ihren bevorzugten Webinspektor, setzen Sie einen Haltepunkt in die Codezeile, die this.loader.src zuweist, und führen Sie diesen Code aus:
Abhängig von Ihrer Anwendung kann das Ersetzen von Zeichen, die außerhalb des Bereichs liegen, funktionieren oder nicht, da Sie die Daten ändern. Beachten Sie den Hinweis auf MDN zu Unicode-Zeichen mit der btoa-Methode:
https://developer.mozilla.org/en-US/docs/Web/API/window.btoa
quelle