2010-09-02 8 views
6

Estoy tratando de base64 codificar una cadena utf8 que contenga caracteres tailandeses. Estoy usando la función integrada del navegador btoa. Funciona para texto ascii, sin embargo, Thai causa que ejecute una excepción INVALID_CHARACTER_ERR: DOM Exception 5.Javascript Base64 que codifica la secuencia UTF8 falla en webkit/safari

He aquí una muestra que falla (el personaje que se parece a una "n" es tailandés)

btoa('aก')


¿Qué necesito hacer para base64 codifican cadenas de caracteres no ASCII?

Respuesta

2

Desafortunadamente btoa/atob no se especifica en ningún estándar, pero las implementaciones en firefox y webkit fallan en los caracteres multibyte, por lo que incluso si ahora se especificaran esas funciones incorporadas no podrían admitir caracteres multibyte (como entrada y las cadenas de salida necesariamente cambiarían).

Parecería que su única opción sería la de rodar su propia base 64 codificar + decodificar rutinas

2
+1

O más específicamente, si quiere copiar/pegar la solución completa: https://developer.mozilla.org/en/DOM/window.btoa#Unicode_Strings (Y si usted está realmente Curioso acerca de cómo funciona y por qué, hay una buena explicación en profundidad de Monsur Hossain sobre su mecánica, en 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

Bueno, debería decir aquí que se va a abandonar el escape. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape Comparta una solución sin usar escape. – TechJS

1

Sé que esto es viejo, pero ha sido recientemente buscando una Codificador UTF8-a-Base64 también. Encontré una pequeña secuencia de comandos útil en http://www.webtoolkit.info/javascript-base64.html, y una versión mejorada de rendimiento en http://jsbase64.codeplex.com/.

Aquí está la secuencia de comandos:

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

de responsabilidad: No he probado esto con caracteres tailandeses específicamente, pero suponer que va a funcionar.

Sav

Cuestiones relacionadas