我有一个可以将PNG图像编码为Base64字符串的PHP脚本。
我想使用JavaScript完成同样的事情。我知道如何打开文件,但是不确定如何进行编码。我不习惯处理二进制数据。
我有一个可以将PNG图像编码为Base64字符串的PHP脚本。
我想使用JavaScript完成同样的事情。我知道如何打开文件,但是不确定如何进行编码。我不习惯处理二进制数据。
你可以使用btoa()
和atob()
来转换成和从base64编码转换。
评论中似乎存在一些关于这些函数接受/返回的内容的混淆,因此...
btoa()
接受一个“字符串”,其中每个字符代表一个8位字节 - 如果您传递包含无法用8位表示的字符的字符串,则它可能会出错。如果您实际上将字符串视为字节数组,则这不是问题,但如果您想要做其他事情,那么您必须首先进行编码。
atob()
返回一个“字符串”,其中每个字符代表一个8位字节 - 也就是说,它的值将介于0
和0xff
之间。这并不意味着它是ASCII - 假定如果您使用该函数,则期望处理二进制数据而不是文本。
这里的大部分评论已经过时了。除非你需要支持非常老旧的浏览器,否则你可以使用btoa()
和atob()
两个函数。
在这里查看:
b 到 a
和 a 到 b
,其中 b 代表二进制,a 代表 ASCII。 - Captain Hypertext从这里开始:
/**
*
* 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;
}
}
此外,搜索"JavaScript base64 encoding"会出现很多其他选项,而上面的是第一个。
string = string.replace(/\r\n/g,"\n");
语句。 - Mariusstring = string.replace(/\r\n/g,"\n");
呢,哈哈。这就像是“哦,让我们对这个字符串进行编码,但首先,为什么不毫无理由地随机规范化所有换行符呢”。在任何情况下,都应该将其从类中删除。 - TriynkoNaN>>4
等于0,但我不知道所有的浏览器是否都这样做(此外,NaN/16
等于NaN)。 - Jan// 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!"
在Node.js中,您可以使用Buffer.fromString将普通文本编码为base64。
/*
Buffer() requires a number, array or string as the first parameter,
and an optional encoding type as the second parameter.
The default is "utf8". Possible encoding types are
"ascii", "utf8", "ucs2", "base64", "binary", and "hex"
*/
var b = Buffer.from('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');
var b = Buffer.from('SmF2YVNjcmlwdA==', 'base64')
var s = b.toString();
var str = dojox.encoding.base64.encode(myByteArray);
var bytes = dojox.encoding.base64.decode(str)
<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=');
}]);
new Buffer()
已被弃用,请使用Buffer.from()
代替。 - Ivan RubinsonBuffer.from("x").toString("base64")
进行编码比使用自己的实现(跨浏览器)更快,但使用自己的实现(跨浏览器)进行解码要快得多。 - Legendary EmojiSunny的代码非常棒,但是由于引用了"this"而在Internet Explorer 7中出现了错误。通过将这些引用替换为"Base64"来修复它。
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
(向Base64转换)和atob
(从Base64转换)。
对于Internet Explorer 9及以下版本,请尝试使用jquery-base64插件:
$.base64.encode("this is a test");
$.base64.decode("dGhpcyBpcyBhIHRlc3Q=");
base64.encode(...)
和 base64.decode(...)
即可。既然它没有任何与jQuery相关的功能,将其附加到jQuery上完全没有意义。 - Jimbo Jonny根据接受答案下方的SET和Stefan Steiger的评论,以下是一份快速摘要,介绍如何在不使用库的情况下对字符串进行Base64编码/解码。
str = "The quick brown fox jumps over the lazy dog";
b64 = btoa(unescape(encodeURIComponent(str)));
str = decodeURIComponent(escape(window.atob(b64)));
const input = document.getElementsByTagName('input')[0];
const btnConv = document.getElementById('btnConv');
const btnDeConv = document.getElementById('btnDeConv');
input.value = "The quick brown fox jumps over the lazy dog";
btnConv.addEventListener('click', () => {
const txt = input.value;
const b64 = btoa(unescape(encodeURIComponent(txt)));
input.value = b64;
btnDeConv.style.display = 'block';
btnConv.style.display = 'none';
});
btnDeConv.addEventListener('click', () => {
var b64 = input.value;
var txt = decodeURIComponent(escape(window.atob(b64)));
input.value = txt;
btnConv.style.display = 'block';
btnDeConv.style.display = 'none';
});
input{width:500px;}
#btnDeConv{display:none;}
<div><input type="text" /></div>
<button id="btnConv">Convert</button>
<button id="btnDeConv">DeConvert</button>
jQuery演示 (使用jQuery库进行显示,但不用于编码/解码)
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>
Buffer.from(b64data, 'base64').toString();
- tycrekunescape
和 escape
是做什么用的吗? - Sámal Rasmussenbtoa
和unescape
和escape
都被标记为已弃用。这里有更多信息:https://dev59.com/plEG5IYBdhLWcg3wR442 和 https://dev59.com/AF4c5IYBdhLWcg3wa5-M#27926636。 - Rocky Kev如果你使用Node.js,你可以这样做:
let a = Buffer.from('JavaScript').toString('base64');
console.log(a);
let b = Buffer.from(a, 'base64').toString();
console.log(b);
两个 _utf8_decode
实现都存在一些错误。由于对 var
语句的错误使用,导致 c1
和 c2
被分配为全局变量,而 c3
则根本没有被初始化或声明。
它可以工作,但是这些变量将覆盖函数外具有相同名称的任何现有变量。
这里有一个不会出现此问题的版本:
// 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;
}
这个问题及其答案指引我朝正确方向。特别是在涉及Unicode时,atob和btoa不能“原汁原味”地使用,而这些日子 所有东西 都是Unicode…
直接从Mozilla获取了两个很好的函数来实现此目的。
已测试带有Unicode和HTML标签的情况:
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"
相较于使用自定义JavaScript函数进行原始Base64解码,这些函数的性能将会非常快速,因为btoa和atob在解释器之外执行。
如果可以忽略旧版Internet Explorer和老款手机(比如iPhone 3?),那么这应该是一个不错的解决方案。
为了让较新的浏览器能够将Uint8Array编码为字符串,并将字符串解码为Uint8Array。
const base64 = {
decode: s => Uint8Array.from(atob(s), c => c.charCodeAt(0)),
encode: b => btoa(String.fromCharCode(...new Uint8Array(b)))
};
对于Node.js,您可以使用以下方式将字符串、缓冲区或Uint8Array编码为字符串,并从字符串、缓冲区或Uint8Array解码为缓冲区。
const base64 = {
decode: s => Buffer.from(s, 'base64'),
encode: b => Buffer.from(b).toString('base64')
};