2010-09-02 19 views
6

Ich versuche Base64 codieren eine UTF8-Zeichenfolge mit Thai-Zeichen. Ich verwende die eingebaute btoa Funktion des Browsers. Es funktioniert für ASCII-Text, aber Thai verursacht es eine INVALID_CHARACTER_ERR: DOM Exception 5 Ausnahme zu werfen.Javascript Base64 Codierung UTF8 String schlägt in Webkit/Safari

Hier ist ein Beispiel, das (das Zeichen, das wie ein "n" aussieht, ist Thai) nicht

btoa('aก')


Was muss ich tun, um base64 Nicht-ASCII-Zeichenketten kodieren?

Antwort

2

Leider sind btoa/atob in keinem Standard angegeben, aber die Implementierungen in Firefox und Webkit schlagen beide auf Multibyte-Zeichen fehl. Selbst wenn sie jetzt spezifiziert wären, könnten diese eingebauten Funktionen Multibyte-Zeichen nicht unterstützen und Ausgabezeichenfolgen würden sich notwendigerweise ändern).

Es wäre Ihre einzige Möglichkeit wäre, Ihre eigene Rolle base64 kodieren + Dekodierungsroutinen

2
+1

Oder genauer gesagt, wenn Sie die vollständige Lösung kopieren/einfügen wollen: https://developer.mozilla.org/en/DOM/window.btoa#Unicode_Strings (Und wenn Sie wirklich sind neugierig darüber, wie es funktioniert und warum, es gibt eine gute eingehende Erklärung von Monsieur Hossain über seine Mechanik, unter http://monsur.hossa.in/2012/07/20/utf-8-in-javascript.html) – ecmanaut

8
var Base64 = { 
    encode: function(s) { 
    return btoa(unescape(encodeURIComponent(s))); 
    }, 
    decode: function(s) { 
    return decodeURIComponent(escape(atob(s))); 
    } 
}; 
+0

Nun, ich sollte hier sagen, dass die Flucht fallen gelassen wird. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape Bitte teilen Sie eine Lösung, ohne escape zu verwenden. – TechJS

1

scheinen Ich weiß, das ist alt, aber ich war auf der Suche vor kurzem für ein UTF8-zu-Base64-Encoder. Ich fand ein praktisches kleines Skript unter http://www.webtoolkit.info/javascript-base64.html und eine leistungsverbesserte Version unter http://jsbase64.codeplex.com/. Hier

ist das Skript:

var B64 = { 
    alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/=', 
    lookup: null, 
    ie: /MSIE /.test(navigator.userAgent), 
    ieo: /MSIE [67]/.test(navigator.userAgent), 
    encode: function (s) { 
     var buffer = B64.toUtf8(s), 
      position = -1, 
      len = buffer.length, 
      nan0, nan1, nan2, enc = [, , , ]; 
     if (B64.ie) { 
      var result = []; 
      while (++position < len) { 
       nan0 = buffer[position]; 
       nan1 = buffer[++position]; 
       enc[0] = nan0 >> 2; 
       enc[1] = ((nan0 & 3) << 4) | (nan1 >> 4); 
       if (isNaN(nan1)) 
        enc[2] = enc[3] = 64; 
       else { 
        nan2 = buffer[++position]; 
        enc[2] = ((nan1 & 15) << 2) | (nan2 >> 6); 
        enc[3] = (isNaN(nan2)) ? 64 : nan2 & 63; 
       } 
       result.push(B64.alphabet.charAt(enc[0]), B64.alphabet.charAt(enc[1]), B64.alphabet.charAt(enc[2]), B64.alphabet.charAt(enc[3])); 
      } 
      return result.join(''); 
     } else { 
      var result = ''; 
      while (++position < len) { 
       nan0 = buffer[position]; 
       nan1 = buffer[++position]; 
       enc[0] = nan0 >> 2; 
       enc[1] = ((nan0 & 3) << 4) | (nan1 >> 4); 
       if (isNaN(nan1)) 
        enc[2] = enc[3] = 64; 
       else { 
        nan2 = buffer[++position]; 
        enc[2] = ((nan1 & 15) << 2) | (nan2 >> 6); 
        enc[3] = (isNaN(nan2)) ? 64 : nan2 & 63; 
       } 
       result += B64.alphabet[enc[0]] + B64.alphabet[enc[1]] + B64.alphabet[enc[2]] + B64.alphabet[enc[3]]; 
      } 
      return result; 
     } 
    }, 
    decode: function (s) { 
     if (s.length % 4) 
      throw new Error("InvalidCharacterError: 'B64.decode' failed: The string to be decoded is not correctly encoded."); 
     var buffer = B64.fromUtf8(s), 
      position = 0, 
      len = buffer.length; 
     if (B64.ieo) { 
      var result = []; 
      while (position < len) { 
       if (buffer[position] < 128) 
        result.push(String.fromCharCode(buffer[position++])); 
       else if (buffer[position] > 191 && buffer[position] < 224) 
        result.push(String.fromCharCode(((buffer[position++] & 31) << 6) | (buffer[position++] & 63))); 
       else 
        result.push(String.fromCharCode(((buffer[position++] & 15) << 12) | ((buffer[position++] & 63) << 6) | (buffer[position++] & 63))); 
      } 
      return result.join(''); 
     } else { 
      var result = ''; 
      while (position < len) { 
       if (buffer[position] < 128) 
        result += String.fromCharCode(buffer[position++]); 
       else if (buffer[position] > 191 && buffer[position] < 224) 
        result += String.fromCharCode(((buffer[position++] & 31) << 6) | (buffer[position++] & 63)); 
       else 
        result += String.fromCharCode(((buffer[position++] & 15) << 12) | ((buffer[position++] & 63) << 6) | (buffer[position++] & 63)); 
      } 
      return result; 
     } 
    }, 
    toUtf8: function (s) { 
     var position = -1, 
      len = s.length, 
      chr, buffer = []; 
     if (/^[\x00-\x7f]*$/.test(s)) while (++position < len) 
      buffer.push(s.charCodeAt(position)); 
     else while (++position < len) { 
      chr = s.charCodeAt(position); 
      if (chr < 128) 
       buffer.push(chr); 
      else if (chr < 2048) 
       buffer.push((chr >> 6) | 192, (chr & 63) | 128); 
      else 
       buffer.push((chr >> 12) | 224, ((chr >> 6) & 63) | 128, (chr & 63) | 128); 
     } 
     return buffer; 
    }, 
    fromUtf8: function (s) { 
     var position = -1, 
      len, buffer = [], 
      enc = [, , , ]; 
     if (!B64.lookup) { 
      len = B64.alphabet.length; 
      B64.lookup = {}; 
      while (++position < len) 
       B64.lookup[B64.alphabet.charAt(position)] = position; 
      position = -1; 
     } 
     len = s.length; 
     while (++position < len) { 
      enc[0] = B64.lookup[s.charAt(position)]; 
      enc[1] = B64.lookup[s.charAt(++position)]; 
      buffer.push((enc[0] << 2) | (enc[1] >> 4)); 
      enc[2] = B64.lookup[s.charAt(++position)]; 
      if (enc[2] == 64) 
       break; 
      buffer.push(((enc[1] & 15) << 4) | (enc[2] >> 2)); 
      enc[3] = B64.lookup[s.charAt(++position)]; 
      if (enc[3] == 64) 
       break; 
      buffer.push(((enc[2] & 3) << 6) | enc[3]); 
     } 
     return buffer; 
    } 
}; 

Disclaimer: Ich habe das nicht mit Thai Zeichen speziell getestet, aber annehmen, dass es funktionieren wird.

Sav