Рубрики
Без рубрики

Кодирование и декодирование строк Base64 в Node.js

Кодирование Base64 – это способ преобразования данных (обычно двоичных) в набор символов ASCII. Здесь важно отметить, что Base64 не является техникой шифрования или сжатия, хотя иногда его можно спутать с шифрованием из-за того, что он как бы скрывает данные.

Что такое кодирование Base64?

Кодирование Base64 – это способ преобразования данных (обычно двоичных) в набор символов ASCII. Здесь важно отметить, что Base64 не является техникой шифрования или сжатия, хотя иногда его можно спутать с шифрованием из-за того, что он как бы скрывает данные. На самом деле, размер закодированной в Base64 части информации в 1,3333 раза превышает реальный размер исходных данных.

Base64 – это наиболее широко используемая техника кодирования базы, а Base16 и Base32 – две другие широко используемые схемы кодирования.

Как работает Base64?

Преобразование данных в base64 – это многоэтапный процесс. Вот как это работает для текстовых строк:

  • Вычислить 8-битную двоичную версию входного текста
  • Перегруппировать 8-битную версию данных в несколько блоков по 6 бит
  • Найти десятичную версию каждого из 6-битных двоичных фрагментов
  • Найти символ Base64 для каждого из десятичных значений с помощью таблицы поиска Base64.

Чтобы лучше понять эту концепцию, давайте рассмотрим пример.

Предположим, у нас есть строка “Go win”, и мы хотим преобразовать ее в строку Base64. Первым шагом будет преобразование этой строки в двоичный формат. Двоичная версия “Go win” имеет следующий вид:

01000111  01101111  00100000  01110111  01101001  01101110

Здесь видно, что каждый символ представлен 8 битами. Однако, как мы уже говорили, Base64 преобразует данные в 8-битной двоичной форме в фрагменты по 6 бит. Это происходит потому, что формат Base64 содержит только 64 символа: 26 заглавных букв алфавита, 26 строчных букв алфавита, 10 цифровых символов, а также символы “+” и “/” для перехода на новую строку.

В Base64 используются не все специальные символы ASCII, а только эти несколько. Обратите внимание, что в некоторых реализациях Base64 используются не “+” и “/”, а другие специальные символы.

Возвращаясь к примеру, давайте разобьем наши 8-битные данные на фрагменты по 6 бит.

010001  110110  111100  100000  011101  110110  100101  101110

Вы не всегда сможете разделить данные на полные наборы по 6 бит, в этом случае вам придется иметь дело с заполнением.

Теперь для каждого приведенного выше куска мы должны найти его десятичное значение. Эти десятичные значения приведены ниже:

Binary  Decimal
010001  17
110110  54
111100  60
100000  32
011101  29
110110  54
100101  37
101110  46

Наконец, мы должны найти значение Base64 для каждого десятичного числа, которое мы только что вычислили из двоичных данных. Таблица кодировки Base64 выглядит следующим образом:

Десятичная к Base64 поиска таблицы

Здесь видно, что десятичное 17 соответствует “R”, а десятичное 54 соответствует “2” и так далее. Используя эту таблицу кодирования, мы видим, что строка “Go win” кодируется как “R28gd2lu” с помощью Base64. Вы можете использовать любой онлайн-конвертер текста в Base64, чтобы проверить этот результат.

Зачем использовать кодировку Base64?

Отправка информации в двоичном формате иногда может быть рискованной, поскольку не все приложения или сетевые системы могут работать с необработанными двоичными данными. С другой стороны, набор символов ASCII широко известен и очень прост в обращении для большинства систем.

Например, серверы электронной почты ожидают текстовых данных, поэтому обычно используется ASCII. Поэтому, если вы хотите отправить изображения или любой другой двоичный файл на сервер электронной почты, вам сначала нужно закодировать его в текстовый формат, предпочтительно ASCII. Именно здесь кодирование Base64 оказывается чрезвычайно полезным для преобразования двоичных данных в нужные форматы.

Кодирование строк Base64 с помощью Node.js

Самый простой способ кодирования строк Base64 в Node.js – через объект Buffer. В Node.js Buffer является глобальным объектом, что означает, что вам не нужно использовать оператор require для того, чтобы использовать объект Buffer в своих приложениях.

Внутри Buffer представляет собой неизменяемый массив целых чисел, который также способен выполнять множество различных кодировок/декодировок. К ним относятся кодировки UTF-8, UCS2, Base64 и даже Hex. Поскольку вы пишете код, который работает с данными и манипулирует ими, вы, вероятно, будете использовать объект Buffer в какой-то момент.

Взгляните на следующий пример. Здесь мы будем кодировать текстовую строку в Base64 с помощью объекта Buffer. Сохраните следующий код в файле “encode-text.js“.

'use strict';

let data = 'stackabuse.com';
let buff = new Buffer(data);
let base64data = buff.toString('base64');

console.log('"' + data + '" converted to Base64 is "' + base64data + '"');

В приведенном выше сценарии мы создаем новый объект buffer и передаем ему нашу строку, которую мы хотим преобразовать в Base64. Затем мы вызываем метод “toString” на объекте буфера, который мы только что создали и передали ему “base64” в качестве параметра. Метод “toString” с “base64” в качестве параметра вернет данные в виде строки Base64. Выполнив приведенный выше код, вы увидите следующий результат.

$ node encode-text.js
"stackabuse.com" converted to Base64 is "c3RhY2thYnVzZS5jb20="

На выходе мы видим аналог Base64 для строки, которую мы преобразовали в Base64.

Декодирование строк Base64 с помощью Node.js

Декодирование строки Base64 очень похоже на ее кодирование. Необходимо создать новый объект buffer и передать два параметра в его конструктор. Первый параметр – это данные в Base64, а второй – “base64”. Затем вы просто должны вызвать “toString” для объекта buffer, но на этот раз параметр, передаваемый методу, будет “ascii”, потому что это тип данных, в который вы хотите преобразовать данные Base64. Для примера посмотрите на следующий фрагмент кода.

'use strict';

let data = 'c3RhY2thYnVzZS5jb20=';
let buff = new Buffer(data, 'base64');
let text = buff.toString('ascii');

console.log('"' + data + '" converted from Base64 to ASCII is "' + text + '"');

Добавьте данные в файл “ascii.js” и сохраните его. Здесь мы использовали “Tm8gdG8gUmFjaXNt” в качестве входных данных Base64. Когда эти данные будут декодированы, должно появиться сообщение “Нет расизму”. Это происходит потому, что из последнего примера мы знаем, что “No to Racism” равно “Tm8gdG8gUmFjaXNt”. Запустите приведенный выше код с помощью Node.js. Он отобразит следующий результат.

Кодирование двоичных данных в строки Base64

Как уже упоминалось в начале статьи, основная цель кодирования Base64 – преобразование двоичных данных в текстовый формат. Давайте рассмотрим пример, в котором мы будем преобразовывать изображение (двоичные данные) в строку Base64. Взгляните на следующий пример.

'use strict';

const fs = require('fs');

let buff = fs.readFileSync('stack-abuse-logo.png');
let base64data = buff.toString('base64');

console.log('Image converted to base 64 is:\n\n' + base64data);

В приведенном выше коде мы загружаем изображение в буфер с помощью метода readFileSync() модуля fs. Остальной процесс аналогичен созданию строки Base64 из обычной ASCII-строки.

При выполнении приведенного выше кода вы увидите следующий результат.

$ node encode-image.js
Image converted to Base64 is:

iVBORw0KGgoAAAANSUhEUgAAABkAAAATCAYAAABlcqYFAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAABWWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpMwidZAAADuUlEQVQ4EbVUTUtcZxR+7ufkXp1SZ4iZRE1EDVQRnTAhowsZMFm40I2rNqUIIev8hvoPQroQXBTqwiAWcd0EglEhiZNajVZrQGXAWAzaZpzMnZn7lXPeeIe5DaWb9Ax33vOec8/znI/3vVI6nfbxP4v8b/iSJIGfzyGfkPi+D13XUalUBL6qqmIvy5+8WuX/r2RCkUzAoIuLi2hqaoLrutjb28P6+josyxJkiqJA07SQXiqVwHaOZYx/itLc3Px9YIxEIlheXsbExATGxsYwMjIiwEdHRwXA/Pw8EokEcrkcDg4OYJomVlZWMDU1JSqfmZlBR0cHbNsOtVoNCHjlTFiSySQMwxAVxONxQbi0tIRMJoPe3l5MT0+jtbUVg4ODYGImY18qlcL4+DhisZjoggCjv1C7uOyenh7Mzs5iY2ND6FQpdnd3sba2JloSjUYxPDyM/v5+TE5OYn9/X9jZtrOzg+3t7WqyAUmoEu419/+HBw9E+eVymbJqAJP39fWBCR3HEU+hUMDQ0JCYGc8um81iYGAAjY2N8DwvwBdraCY8tHhDA1Y3N9Hd3S2yvH37O7RcbsF7AuUsD9+8wdOFBTx/8QJtbW1C5/nMzc3R0D2UyxXk83lRXcAk1V5GCT5sSUGDbeHxy9/EO98M9OOXzT9wfHISxKC1vR0GHfOtrS2g/SouWwU0Xkggu7qO9PUkJFULnbIQyTm6ewu2hF+vnOIIUQwdGlg8f4QF6wvMWBq+pAkaskSnx4FFVUf0CNpcC797KizXQ4oAHhVdXJJ81F7j6kwUynPHlXDPdFB2fRj+KVK0KvT2rbp3uKYryJU11Cke8qqMuOoioeeJ1MPDYxM36m1cNSq4GdFx58RAWvbx8TrXnK4IgR16Em5GK4iqHi5GHHxLgcSDn97WgZPoND+GGZRpPYH85cgiiRQl1ltXxmFFQ5PuopP8TrW5ZyRcWp7AbmkeZefg5+N6PPnbRJdpw/YlfB0vQiPQZwVdZNtFZEVK6D1VTnccJlXzuqTjvOZiq6Rhj2KqLSJsofOHgIl8+t0/qsfDioxmSUWGjrRFzhYi/5Oynrdl3KXHIZDXtF6hil8R6I9FBV/RvDLnXKxSbAdVYhNeINXBMwmXWCTQGG2Y+Jj+dFrfEmiMAtmeowpo9ojTvkD+A/L1UJUMmiVfkuz6WTyZhFRJAgP33j3bsM5k/Fng68UP21hYJyyxZwLWuS2cKMfUSm3rhD0g4E2g197fwMZ+Bgt8rNe2iP2BhL5dgfFzrx8AfECEDdx45a0AAAAASUVORK5CYII=

Хотя фактическое изображение очень маленькое (25×19), результат все равно довольно большой, отчасти потому, что Base64 увеличивает размер данных, как мы уже говорили ранее.

Декодирование строк Base64 в двоичные данные

Обратный процесс здесь очень похож на то, как мы декодируем строки Base64, как мы видели в предыдущем разделе. Самое большое различие заключается в месте назначения вывода и в том, как туда записываются данные. Рассмотрим пример:

'use strict';

const fs = require('fs');

let data = 'iVBORw0KGgoAAAANSUhEUgAAABkAAAATCAYAAABlcqYFAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAA' + 
'CA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAABWWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0' +
'YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly' +
'93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAg' +
'ICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZm' +
'Y6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpMwidZAAADuUlEQVQ4EbVU' +
'TUtcZxR+7ufkXp1SZ4iZRE1EDVQRnTAhowsZMFm40I2rNqUIIev8hvoPQroQXBTqwiAWcd0EglEhiZNajVZrQGXAWAzaZpzMnZn7lXPeeIe5Da' +
'Wb9Ax33vOec8/znI/3vVI6nfbxP4v8b/iSJIGfzyGfkPi+D13XUalUBL6qqmIvy5+8WuX/r2RCkUzAoIuLi2hqaoLrutjb28P6+josyxJkiqJA' +
'07SQXiqVwHaOZYx/itLc3Px9YIxEIlheXsbExATGxsYwMjIiwEdHRwXA/Pw8EokEcrkcDg4OYJomVlZWMDU1JSqfmZlBR0cHbNsOtVoNCHjlTF' +
'iSySQMwxAVxONxQbi0tIRMJoPe3l5MT0+jtbUVg4ODYGImY18qlcL4+DhisZjoggCjv1C7uOyenh7Mzs5iY2ND6FQpdnd3sba2JloSjUYxPDyM' +
'/v5+TE5OYn9/X9jZtrOzg+3t7WqyAUmoEu419/+HBw9E+eVymbJqAJP39fWBCR3HEU+hUMDQ0JCYGc8um81iYGAAjY2N8DwvwBdraCY8tHhDA1' +
'Y3N9Hd3S2yvH37O7RcbsF7AuUsD9+8wdOFBTx/8QJtbW1C5/nMzc3R0D2UyxXk83lRXcAk1V5GCT5sSUGDbeHxy9/EO98M9OOXzT9wfHISxKC1' +
'vR0GHfOtrS2g/SouWwU0Xkggu7qO9PUkJFULnbIQyTm6ewu2hF+vnOIIUQwdGlg8f4QF6wvMWBq+pAkaskSnx4FFVUf0CNpcC797KizXQ4oAHh' +
'VdXJJ81F7j6kwUynPHlXDPdFB2fRj+KVK0KvT2rbp3uKYryJU11Cke8qqMuOoioeeJ1MPDYxM36m1cNSq4GdFx58RAWvbx8TrXnK4IgR16Em5G' +
'K4iqHi5GHHxLgcSDn97WgZPoND+GGZRpPYH85cgiiRQl1ltXxmFFQ5PuopP8TrW5ZyRcWp7AbmkeZefg5+N6PPnbRJdpw/YlfB0vQiPQZwVdZN' +
'tFZEVK6D1VTnccJlXzuqTjvOZiq6Rhj2KqLSJsofOHgIl8+t0/qsfDioxmSUWGjrRFzhYi/5Oynrdl3KXHIZDXtF6hil8R6I9FBV/RvDLnXKxS' +
'bAdVYhNeINXBMwmXWCTQGG2Y+Jj+dFrfEmiMAtmeowpo9ojTvkD+A/L1UJUMmiVfkuz6WTyZhFRJAgP33j3bsM5k/Fng68UP21hYJyyxZwLWuS' +
'2cKMfUSm3rhD0g4E2g197fwMZ+Bgt8rNe2iP2BhL5dgfFzrx8AfECEDdx45a0AAAAASUVORK5CYII=';

let buff = new Buffer(data, 'base64');
fs.writeFileSync('stack-abuse-logo-out.png', buff);

console.log('Base64 image data converted to file: stack-abuse-logo-out.png');

Здесь видно, что мы начинаем с данных в формате Base64 (которые также могли быть получены из сокета или другой линии связи) и загружаем их в объект Buffer. При создании буфера мы сообщаем ему, что данные находятся в формате base64, что позволяет буферу соответствующим образом разобрать их для внутреннего хранения.

Чтобы сохранить данные в исходном формате PNG, мы просто передаем объект Buffer в метод fs.writeFileSync, и он выполняет преобразование за нас.

Заключение

Кодирование Base64 является одним из наиболее распространенных способов преобразования двоичных данных в простой текст ASCII. Это очень полезный формат для обмена данными между одной или несколькими системами, которые не могут легко обрабатывать двоичные данные, например, изображения в HTML-разметке или веб-запросы.

В Node.js объект Buffer можно использовать для кодирования и декодирования строк Base64 во многие другие форматы и обратно, что позволяет легко преобразовывать данные туда и обратно по мере необходимости.

Оригинал: “https://stackabuse.com/encoding-and-decoding-base64-strings-in-node-js/”