Кодирование и декодирование Base64 в Javascript на стороне клиента
Есть ли в JavaScript какие-либо методы, которые можно было бы использовать для кодирования и декодирования строки с использованием кодировки base64?
17 ответов
Некоторые браузеры, такие как Firefox, Chrome, Safari, Opera и IE10+, могут работать с Base64 изначально. Посмотрите на этот вопрос Stackru. Он использует btoa()
а также atob()
функции
Для серверного JavaScript есть пакет btoa для Node.JS.
Если вы собираетесь использовать кросс-браузерное решение, существуют существующие библиотеки, такие как CryptoJS или код, подобный следующему:
http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html
Что касается последнего, вам необходимо тщательно протестировать функцию на совместимость с различными браузерами. И об ошибке уже сообщалось.
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!"
Кросс-браузер
Переписанные и модульные библиотеки / модули кодирования и декодирования JavaScript UTF-8 и Base64 для AMD, CommonJS, Nodejs и браузеров. Кросс-браузер совместим.
с Node.js
Вот как вы кодируете обычный текст в base64 в Node.js:
//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:
var b = new Buffer('SmF2YVNjcmlwdA==', 'base64')
var s = b.toString();
с Dojo.js
Для кодирования массива байтов с использованием dojox.encoding.base64:
var str = dojox.encoding.base64.encode(myByteArray);
Чтобы декодировать строку в кодировке base64:
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=');
}]);
Но как?
Если вы хотите узнать больше о том, как base64 кодируется в целом, и, в частности, в JavaScript, я бы порекомендовал эту статью: Информатика в JavaScript: кодирование Base64
В браузерах на основе Gecko/WebKit (Firefox, Chrome и Safari) и Opera вы можете использовать btoa() и atob ().
Оригинальный ответ: Как вы можете кодировать строку в Base64 в JavaScript?
Вот сжатая версия сообщения Снайпера. Предполагается, что правильно сформированная строка base64 без возврата каретки. Эта версия устраняет пару петель, добавляет &0xff
исправление от Ярослава, устраняет завершающие нули, плюс немного кода гольф.
decodeBase64 = function(s) {
var e={},i,b=0,c,x,l=0,a,r='',w=String.fromCharCode,L=s.length;
var A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
for(i=0;i<64;i++){e[A.charAt(i)]=i;}
for(x=0;x<L;x++){
c=e[s.charAt(x)];b=(b<<6)+c;l+=6;
while(l>=8){((a=(b>>>(l-=8))&0xff)||(x<(L-2)))&&(r+=w(a));}
}
return r;
};
Короткая и быстрая функция декодирования JavaScript Base64 без Failsafe:
function decode_base64 (s)
{
var e = {}, i, k, v = [], r = '', w = String.fromCharCode;
var n = [[65, 91], [97, 123], [48, 58], [43, 44], [47, 48]];
for (z in n)
{
for (i = n[z][0]; i < n[z][1]; i++)
{
v.push(w(i));
}
}
for (i = 0; i < 64; i++)
{
e[v[i]] = i;
}
for (i = 0; i < s.length; i+=72)
{
var b = 0, c, x, l = 0, o = s.substring(i, i+72);
for (x = 0; x < o.length; x++)
{
c = e[o.charAt(x)];
b = (b << 6) + c;
l += 6;
while (l >= 8)
{
r += w((b >>> (l -= 8)) % 256);
}
}
}
return r;
}
function b64_to_utf8( str ) {
return decodeURIComponent(escape(window.atob( str )));
}
https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22
Современные браузеры имеют встроенные функции javascript для кодирования Base64 btoa() и декодирования atob (). Подробнее о поддержке в старых версиях браузеров: https://caniuse.com/?search=atob
Однако имейте в виду, что
atob
и
btoa
функции работают только для кодировки ASCII. Если вам нужны функции Base64 для кодировки UTF-8, вы можете сделать это с помощью:
function base64_encode(s) {
return btoa(unescape(encodeURIComponent(s)));
}
function base64_decode(s) {
return decodeURIComponent(escape(atob(s)));
}
Кто-то сказал код гольф? знак равно
Следующее - моя попытка улучшить мой гандикап, не отставая от времени. Поставляется для вашего удобства.
function decode_base64(s) {
var b=l=0, r='',
m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
s.split('').forEach(function (v) {
b=(b<<6)+m.indexOf(v); l+=6;
if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
});
return r;
}
То, чем я был на самом деле после, было асинхронной реализацией, и, к моему удивлению, оказалось forEach
в отличие от JQuery's $([]).each
Реализация метода очень синхронна.
Если вы также имели в виду такие сумасшедшие понятия, задержка 0 window.setTimeout
выполнит декодирование base64 асинхронно и выполнит функцию обратного вызова с результатом, когда это будет сделано.
function decode_base64_async(s, cb) {
setTimeout(function () { cb(decode_base64(s)); }, 0);
}
@Toothbrush предложил "проиндексировать строку как массив" и избавиться от split
, Эта процедура кажется действительно странной и не уверенной, насколько она будет совместимой, но она поражает другую птичку, так что давайте ее получим.
function decode_base64(s) {
var b=l=0, r='',
m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
[].forEach.call(s, function (v) {
b=(b<<6)+m.indexOf(v); l+=6;
if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
});
return r;
}
Пытаясь найти больше информации о строке JavaScript в виде массива, я наткнулся на этот профессиональный совет, используя /./g
регулярное выражение, чтобы пройти через строку. Это еще больше уменьшает размер кода, заменяя строку на месте и избавляя от необходимости сохранять возвращаемую переменную.
function decode_base64(s) {
var b=l=0,
m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
return s.replace(/./g, function (v) {
b=(b<<6)+m.indexOf(v); l+=6;
return l<8?'':String.fromCharCode((b>>>(l-=8))&0xff);
});
}
Однако, если вы ищете что-то более традиционное, возможно, вам больше понравится.
function decode_base64(s) {
var b=l=0, r='', s=s.split(''), i,
m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
for (i in s) {
b=(b<<6)+m.indexOf(s[i]); l+=6;
if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
}
return r;
}
У меня не было завершающей нулевой проблемы, поэтому она была удалена, чтобы остаться на уровне номинала, но ее легко можно решить с помощью trim()
или trimRight()
если вы предпочитаете, это должно создать для вас проблему.
то есть.
return r.trimRight();
Замечания:
В результате получается строка байтов ascii, если вам нужен юникод, проще всего escape
строка байтов, которая затем может быть декодирована decodeURIComponent
для получения строки Unicode.
function decode_base64_usc(s) {
return decodeURIComponent(escape(decode_base64(s)));
}
поскольку escape
не рекомендуется, мы могли бы изменить нашу функцию для поддержки Unicode напрямую без необходимости escape
или же String.fromCharCode
мы можем произвести %
экранированная строка готова для декодирования URI.
function decode_base64(s) {
var b=l=0,
m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
return decodeURIComponent(s.replace(/./g, function (v) {
b=(b<<6)+m.indexOf(v); l+=6;
return l<8?'':'%'+(0x100+((b>>>(l-=8))&0xff)).toString(16).slice(-2);
}));
}
NJoy!
Проект php.js имеет реализации JavaScript многих функций PHP. base64_encode
а также base64_decode
включены.
Как бы то ни было, меня вдохновили другие ответы, и я написал небольшую утилиту, которая вызывает API-интерфейсы, специфичные для платформы, для универсального использования либо из Node.js, либо из браузера:
/**
* Encode a string of text as base64
*
* @param data The string of text.
* @returns The base64 encoded string.
*/
function encodeBase64(data: string) {
if (typeof btoa === "function") {
return btoa(data);
} else if (typeof Buffer === "function") {
return Buffer.from(data, "utf-8").toString("base64");
} else {
throw new Error("Failed to determine the platform specific encoder");
}
}
/**
* Decode a string of base64 as text
*
* @param data The string of base64 encoded text
* @returns The decoded text.
*/
function decodeBase64(data: string) {
if (typeof atob === "function") {
return atob(data);
} else if (typeof Buffer === "function") {
return Buffer.from(data, "base64").toString("utf-8");
} else {
throw new Error("Failed to determine the platform specific decoder");
}
}
Вот лучший способ для base64_encode и base64_decode, используя javascript. Смотрите ниже ссылки.
Я попробовал подпрограммы Javascript на phpjs.org, и они работали хорошо.
Сначала я попробовал процедуры, предложенные в выбранном ответе Ранхиру Курей - http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html
Я обнаружил, что они не работают при любых обстоятельствах. Я написал тестовый пример, где эти подпрограммы потерпели неудачу, и разместил их на GitHub по адресу:
https://github.com/scottcarter/base64_javascript_test_data.git
Я также разместил комментарий к сообщению в блоге по адресу ntt.cc, чтобы предупредить автора (ожидает модерации - статья старая, поэтому не уверен, что комментарий будет опубликован).
Фронтенд: хорошие решения выше, но быстро для бэкэнда ...
NodeJS - без устаревания
Использовать
Buffer.from
.
> inBase64 = Buffer.from('plain').toString('base64')
'cGxhaW4='
> // DEPRECATED //
> new Buffer(inBase64, 'base64').toString()
'plain'
> (node:1188987) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
// Works //
> Buffer.from(inBase64, 'base64').toString()
'plain'
В Node.js мы можем сделать это простым способом
var base64 = 'SGVsbG8gV29ybGQ='
var base64_decode = new Buffer(base64, 'base64').toString('ascii');
console.log(base64_decode); // "Hello World"
Для фреймворков JavaScripts, где нет atob
метод, и в случае, если вы не хотите импортировать внешние библиотеки, это небольшая функция, которая делает это.
Он получит строку, содержащую значение в кодировке Base64, и вернет декодированный массив байтов (где массив байтов представлен как массив чисел, где каждое число является целым числом от 0 до 255 включительно).
function fromBase64String(str) {
var alpha =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var value = [];
var index = 0;
var destIndex = 0;
var padding = false;
while (true) {
var first = getNextChr(str, index, padding, alpha);
var second = getNextChr(str, first .nextIndex, first .padding, alpha);
var third = getNextChr(str, second.nextIndex, second.padding, alpha);
var fourth = getNextChr(str, third .nextIndex, third .padding, alpha);
index = fourth.nextIndex;
padding = fourth.padding;
// ffffffss sssstttt ttffffff
var base64_first = first.code == null ? 0 : first.code;
var base64_second = second.code == null ? 0 : second.code;
var base64_third = third.code == null ? 0 : third.code;
var base64_fourth = fourth.code == null ? 0 : fourth.code;
var a = (( base64_first << 2) & 0xFC ) | ((base64_second>>4) & 0x03);
var b = (( base64_second<< 4) & 0xF0 ) | ((base64_third >>2) & 0x0F);
var c = (( base64_third << 6) & 0xC0 ) | ((base64_fourth>>0) & 0x3F);
value [destIndex++] = a;
if (!third.padding) {
value [destIndex++] = b;
} else {
break;
}
if (!fourth.padding) {
value [destIndex++] = c;
} else {
break;
}
if (index >= str.length) {
break;
}
}
return value;
}
function getNextChr(str, index, equalSignReceived, alpha) {
var chr = null;
var code = 0;
var padding = equalSignReceived;
while (index < str.length) {
chr = str.charAt(index);
if (chr == " " || chr == "\r" || chr == "\n" || chr == "\t") {
index++;
continue;
}
if (chr == "=") {
padding = true;
} else {
if (equalSignReceived) {
throw new Error("Invalid Base64 Endcoding character \""
+ chr + "\" with code " + str.charCodeAt(index)
+ " on position " + index
+ " received afer an equal sign (=) padding "
+ "character has already been received. "
+ "The equal sign padding character is the only "
+ "possible padding character at the end.");
}
code = alpha.indexOf(chr);
if (code == -1) {
throw new Error("Invalid Base64 Encoding character \""
+ chr + "\" with code " + str.charCodeAt(index)
+ " on position " + index + ".");
}
}
break;
}
return { character: chr, code: code, padding: padding, nextIndex: ++index};
}
Используемые ресурсы: RFC-4648, раздел 4
Декодирование Base64 Win-1251 для кодировок, отличных от acsi или iso-8859-1.
Как оказалось, все скрипты, которые я здесь видел, конвертируют кириллицу Base64 в кодировку iso-8859-1. Странно, что этого никто не заметил.
Таким образом, для восстановления кириллицы достаточно произвести дополнительную перекодировку текста с iso-8859-1 на windows-1251.
Думаю, что и с другими языками будет так же. Просто смени кириллицу windows-1251 на свою.
... и спасибо Der Hochstapler за его код, я взял из его комментария ... излишнего комментария, что несколько необычно.
код для JScript (только для рабочего стола Windows) (ActiveXObject) - кодировка файла 1251
decode_base64=function(f){var g={},b=65,d=0,a,c=0,h,e="",k=String.fromCharCode,l=f.length;for(a="";91>b;)a+=k(b++);a+=a.toLowerCase()+"0123456789+/";for(b=0;64>b;b++)g[a.charAt(b)]=b;for(a=0;a<l;a++)for(b=g[f.charAt(a)],d=(d<<6)+b,c+=6;8<=c;)((h=d>>>(c-=8)&255)||a<l-2)&&(e+=k(h));return e};
sDOS2Win = function(sText, bInsideOut) {
var aCharsets = ["iso-8859-1", "windows-1251"];
sText += "";
bInsideOut = bInsideOut ? 1 : 0;
with (new ActiveXObject("ADODB.Stream")) { //http://www.w3schools.com/ado/ado_ref_stream.asp
type = 2; //Binary 1, Text 2 (default)
mode = 3; //Permissions have not been set 0, Read-only 1, Write-only 2, Read-write 3,
//Prevent other read 4, Prevent other write 8, Prevent other open 12, Allow others all 16
charset = aCharsets[bInsideOut];
open();
writeText(sText);
position = 0;
charset = aCharsets[1 - bInsideOut];
return readText();
}
}
var base64='0PPx8ero5SDh8+ru4uroIQ=='
text = sDOS2Win(decode_base64(base64), false );
WScript.Echo(text)
var x=WScript.StdIn.ReadLine();