如何在JavaScript中将string编码为Base64?
我有一个PHP脚本,可以将PNG图像编码为Base64string。
我想用JavaScript来做同样的事情。 我知道如何打开文件,但我不知道如何做的编码? 我不习惯使用二进制数据。
你可以使用btoa()
和atob()
来转换和从base64编码。
关于这些function接受/返回的意见似乎有些混乱,所以…
-
btoa()
接受一个“string”,其中每个字符代表一个8位的字节 – 如果你传递的string包含不能用8位表示的字符, 它可能会中断 。 如果实际上将string视为字节数组,那么这不是问题,但是如果您正在尝试执行其他操作,则必须先对其进行编码。 -
atob()
返回一个“string”,其中每个字符代表一个8位字节 – 也就是说,它的值将在0
到0xff
之间。 这并不意味着它是ASCII – 大概如果你使用这个函数,你希望使用二进制数据而不是文本。
也可以看看:
- 如何使用JavaScript和XMLHttpRequest加载二进制图像数据?
从这里 :
/** * * 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; } }
此外,search“JavaScript的base64编码”变成了很多其他的select,以上是第一个。
Sunny的代码很好,除了因为引用“this”而在IE7中破解的代码。 通过用“Base64”replace这样的引用来修复:
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; } }
你可以使用btoa
(base-64)和atob
(base-64)。
对于IE 9及以下版本,请尝试jquery-base64插件:
$.base64.encode("this is a test"); $.base64.decode("dGhpcyBpcyBhIHRlc3Q=");
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!"
跨浏览器
// 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
与Node.js
以下是在Node.js中如何将普通文本编码为base64:
//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');
这里是你如何解码base64编码的string:
var b = new Buffer('SmF2YVNjcmlwdA==', 'base64') var s = b.toString();
与Dojo.js
使用dojox.encoding.base64对字节数组进行编码:
var str = dojox.encoding.base64.encode(myByteArray);
解码base64编码的string:
var bytes = dojox.encoding.base64.decode(str)
凉亭安装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='); }]);
在_utf8_decode
两个实现中都有一些bug。 由于var
语句的使用被破坏, c1
和c2
被指定为全局variables,而c3
根本没有被初始化或声明。
它可以工作,但是这些variables将会覆盖这个函数之外的所有现有的同名variables。
这是一个不会这样做的版本:
// 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; }
我对Sunny的答案+1了,但是我想回复一下我为自己的项目所做的一些改变,以防有人发现它有用。 基本上我刚刚清理了一些原始的代码,所以JSLint没有太多抱怨,而且我把这些方法标记为私有的。 我还在自己的项目中添加了两个我需要的方法,即decodeToHex
和encodeFromHex
。
代码:
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 }; }());
我已经手工重写了这些编码和解码方法,除了hex之外,还有跨平台/浏览器兼容的模块化格式,还有真正的私有范围,如果存在速度而使用btoa
和atob
比利用自己的编码:
https://gist.github.com/Nijikokun/5192472
用法:
base64.encode(/* String */); base64.decode(/* String */); utf8.encode(/* String */); utf8.decode(/* String */);
为了使一个Base64编码的stringURL友好,在JavaScript中你可以做这样的事情:
// 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, '/');
另见这个小提琴: http : //jsfiddle.net/magikMaker/7bjaT/
如果您需要对HTML图像对象进行编码,则可以编写如下简单的函数:
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 }
通过id获得图像的base64:
function getBase64ImageById(id){ return getBase64Image(document.getElementById(id)); }
这里更多
请注意,这不适用于原始的Unicodestring! 在这里看到Unicode部分。
编码的语法
var encodedData = window.btoa(stringToEncode);
解码的语法
var decodedData = window.atob(encodedData);
为我正在使用的window.atob
+ window.btoa
提供一个缩小的polyfill。
(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})})();
这个问题和答案指向了正确的方向。
特别是与unicode atob和btoa不能使用“香草”,这些天,一切都unicode ..
直接从Mozilla,这两个很好的function(用unicode和html标签内部testing)
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"
与原始的base64解码相比,这些函数的执行速度会快得多,因为btoa和atob是在解释器之外执行的。
如果你可以忽略旧的IE和老的手机(如iPhone 3?),这应该是一个很好的解决scheme。
我宁愿使用来自CryptoJS的bas64编码/解码方法, CryptoJS是使用最佳实践和模式在JavaScript中实现的最stream行的标准和安全encryptionalgorithm库。
这里是@ user850789的一个AngularJS Factory版本:
'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; });
我需要一个UTF-8string编码为base64为我的一个项目。 大多数的答案在转换为UTF-8的时候似乎并没有正确处理UTF-16代理对,所以为了完成,我将发布我的解决scheme:
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(''); }
请注意,代码没有经过彻底的testing。 我testing了一些input,包括像strToUTF8Base64('衠衢蠩蠨')
并与在线编码工具( https://www.base64encode.org/ )的输出进行比较。
对于我的项目,我仍然需要支持IE7,并使用大量input进行编码。
根据Joe Dyndale提出的代码和Marius的build议,通过用数组而不是string构造结果,可以提高IE7的性能。
这里是编码的例子:
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(""); };
那么,如果你使用的是dojo,它给了我们直接的编码或解码成base64的方法。
尝试这个:-
使用dojox.encoding.base64对字节数组进行编码:
var str = dojox.encoding.base64.encode(myByteArray);
解码base64编码的string:
var bytes = dojox.encoding.base64.decode(str);
虽然工作多一点,但如果您想要一个高性能的本机解决scheme,则可以使用一些HTML5函数。
如果您可以将数据存入Blob
,那么可以使用FileReader.readAsDataURL()函数来获取data://
URL,然后切掉它的前面以获取base64数据。
你可能需要做进一步的处理,然后urldecode数据,因为我不知道是否+
字符是逃脱或没有data://
URL,但这应该是相当平凡的。
From the comments (by SET and Stephan Steiger) below the accepted answer, here is a quick summary of how to encode/decode a string to/from base64 without need of a library.
str = "The quick brown fox jumps over the lazy dog" b64 = btoa(unescape(encodeURIComponent(str)))) str = decodeURIComponent(escape(window.atob(b64)));
演示
(uses jQuery library, but not for encode/decode)
str = "The quick brown fox jumps over the lazy dog"; $('input').val(str); $('#btnConv').click(function(){ var txt = $('input').val(); var b64 = btoa(unescape(encodeURIComponent(txt))); $('input').val(b64); $('#btnDeConv').show(); }); $('#btnDeConv').click(function(){ var b64 = $('input').val(); var txt = decodeURIComponent(escape(window.atob(b64))); $('input').val(txt); });
#btnDeConv{display:none;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <input type="text" /> <button id="btnConv">Convert</button> <button id="btnDeConv">DeConvert</button>