Одна статья для понимания кодировки base64

внешний интерфейс JavaScript
Одна статья для понимания кодировки base64

1. Зачем использовать base64

Мы знаем, что диапазон, который может представлять байт, составляет от 0 до 255 (шестнадцатеричный: от 0x00 до 0xFF), а диапазон значений ASCII — от 0 до 127 (шестнадцатеричный: от 0x00 до 0x7F); и 128 за пределами диапазона значений ASCII. между ~255 (hex: от 0x80 до 0xFF) невидимые символы.

ASCII (Американский стандартный код для обмена информацией) — это компьютерная система кодирования, основанная на латинском алфавите. В основном он используется для отображения современного английского языка, но его расширенная версия, Американский стандартный код для обмена информацией, может частично поддерживать другие западноевропейские языки и эквивалентна международному стандарту ISO/IEC 646.

В ASCII от 0 до 31 и 127 являются управляющими символами, всего 33. Ниже приведены некоторые из управляющих символов:

ascii-controller-table

Остальные 95, или от 32 до 126, являются печатными символами, включая цифры, прописные и строчные буквы, общеупотребительные символы и т. д.

ascii-printable-table

Когда невидимые символы передаются по сети, например, с компьютера А на компьютер Б, они часто проходят через несколько устройств маршрутизации.Поскольку разные устройства обрабатывают символы по-разному, эти невидимые символы могут передаваться.Обрабатывать ошибки, что нехорошо для транспорта.Чтобы решить эту проблему, мы можем сначала закодировать данные, такие как кодировка base64, в видимые символы, то есть видимые символы, которые могут быть представлены кодом ASCII, чтобы обеспечить надежную передачу данных. Содержимое Base64 состоит из 0 ~ 9, a ~ z, A ~ Z, +, / и содержит ровно 64 символа.Эти символы находятся в диапазоне, который может быть представлен ASCII, и являются частью 95 видимых символов. .

2. Что такое base64

Base64представляет собой представление двоичных данных, основанное на 64 печатных символах. Поскольку 2⁶ = 64, каждые 6 бит являются единицей, соответствующей печатному символу. 3 байта имеют 24 бита, что соответствует 4 единицам base64, т. е. 3 байта могут быть представлены 4 печатными символами. Соответствующий процесс преобразования показан на следующем рисунке:

base64-convert

**Base64 часто используется для представления, передачи и хранения некоторых двоичных данных, включая электронные письма MIME и некоторые сложные данные в XML, при работе с текстовыми данными. ** В электронной почте в формате MIME base64 может использоваться для кодирования данных последовательности двоичных байтов в текст, состоящий из последовательности символов ASCII. При использовании укажите base64 в методе кодирования передачи. Используемые символы включают 26 прописных и строчных латинских букв, 10 цифр, знак плюс + и косую черту /, всего 64 символа, а знак равенства = используется в качестве суффикса. Соответствующая индексная таблица Base64 выглядит следующим образом:

base64-encode-table

Поняв вышеизложенные знания, давайте кодManВозьмите в качестве примера строку, чтобы интуитивно почувствовать процесс кодирования.ManОн состоит из M, a и n 3 символов, соответствующие им коды ASCII — 77, 97 и 110.

char-m-ascii

Затем мы выполняем операцию кодирования base64 с каждыми 6 битами как единицей, как показано на следующем рисунке:

base64-encode-demo

На рисунке показано,Man(3 байта) закодированный результатTWFu(4 байта), очевидно, объем увеличится на 1/3 после кодирования base64.ManДлина этой строки ровно 3, что мы можем представить в 4 единицах base64. Но что, если длина кодируемой строки не является целым числом, кратным 3?

Если количество кодируемых байтов не делится на 3, а в конце будут лишние 1 или 2 байта, то с этим можно справиться следующим способом: сначала использовать 0-байтовое значение, чтобы компенсировать конец, чтобы он делился на 3, затем выполните кодировку base64.

Взяв закодированный символ A в качестве примера, количество байтов, которое он занимает, равно 1, что не может делиться на 3 и должно быть дополнено 2 байтами, как показано на следующем рисунке:

base64-encode-a

Как видно из приведенного выше рисунка, результат символа A после кодирования base64 равенQQ==, два следующих за результатом=Представляет количество байтов, которые необходимо восполнить. И последний 1 блок байтов base64 имеет 4 бита со значением 0.

Давайте посмотрим на другой пример, предположим, что кодируемая строка имеет видBC, число байтов, которое он занимает, равно 2, что не может делиться на 3 и должно быть дополнено 1 байтом, как показано на следующем рисунке:

base64-encode-bc

Как видно из приведенного выше рисунка, результат кодирования base64 строки BC равенQkM=, 1 после результата=Представляет количество байтов, которые необходимо восполнить. И последний 1 блок байтов base64 имеет 2 бита со значением 0.

В-третьих, применение кодировки base64

3.1 Отображение изображений в кодировке base64

При написании веб-страниц в формате HTML для некоторых простых изображений обычно выбирают встраивание содержимого изображения непосредственно в веб-страницу, тем самым уменьшая ненужные сетевые запросы, но данные изображения являются двоичными данными, как их встроить? Большинство современных браузеров поддерживаютData URLsФункция, позволяющая кодировать двоичные данные изображений или других файлов с использованием base64 для встраивания в веб-страницы в виде текстовых строк.

URL-адреса данных состоят из четырех частей: префикса (data:), тип MIME, указывающий тип данных, необязательный, если нетекстовыйbase64Тег, сами данные:

data:[<mediatype>][;base64],<data>

mediatypeявляется строкой типа MIME, например, "image/jpeg" означает файл изображения в формате JPEG. Если этот параметр опущен, по умолчаниюtext/plain;charset=US-ASCII. Если данные имеют текстовый тип, вы можете внедрить текст напрямую (используя соответствующие символы сущности или escape-символы в зависимости от типа документа). Если это двоичные данные, вы можете закодировать данные в base64 перед встраиванием. Например, чтобы вставить изображение:

<img alt="logo" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...">

MIME (многоцелевые расширения почты Интернета) — это тип многоцелевого расширения почты Интернета, который представляет собой способ установить файл с определенным расширением для открытия приложением.При доступе к файлу расширения браузер будет автоматически использовать указанный расширение приложение для открытия. Он в основном используется для указания некоторых определяемых клиентом имен файлов, а также некоторых методов открытия медиафайлов.

Общие типы MIME: язык гипертекстовой разметки text .html text/html, изображение PNG .png image/png, обычный текст .txt text/plain и т. д.

Однако следует отметить, что если изображение большое и цветовой уровень изображения насыщенный, использовать этот метод нецелесообразно, так как строка, закодированная base64 изображения, очень велика, что значительно увеличит размер HTML-страницы, тем самым влияя на размер HTML-страницы, скорость загрузки.Кроме того, используя HTML FileReader API, мы также можем легко реализовать функцию предварительного просмотра локального изображения.Конкретный код выглядит следующим образом:

<input type="file" accept="image/*" onchange="loadFile(event)">
<img id="output"/>
<script>
  const loadFile = function(event) {
    const reader = new FileReader();
    reader.onload = function(){
      const output = document.querySelector('output');
      output.src = reader.result;
    };
    reader.readAsDataURL(event.target.files[0]);
  };
</script>

После завершения локального предварительного просмотра изображения вы можете напрямую отправить данные URL-адресов данных, соответствующие изображению, на сервер. В ответ на эту ситуацию серверу необходимо выполнить некоторую связанную обработку, чтобы нормально сохранить загруженные изображения.ExpressНапример, конкретный код обработки выглядит следующим образом:

const app = require('express')();

app.post('/upload', function(req, res){
    let imgData = req.body.imgData; // 获取POST请求中的base64图片数据
    let base64Data = imgData.replace(/^data:image\/\w+;base64,/, "");
    let dataBuffer = Buffer.from(base64Data, 'base64');
    fs.writeFile("image.png", dataBuffer, function(err) {
        if(err){
          res.send(err);
        }else{
          res.send("图片上传成功!");
        }
    });
});

3.2 Сжатие изображений на стороне браузера

В некоторых случаях мы надеемся, что при загрузке локального изображения изображение сначала сжимается до определенной степени, а затем отправляется на сервер, тем самым уменьшая объем передаваемых данных. Чтобы добиться сжатия изображения во внешнем интерфейсе, мы можем использовать предоставленный объект Canvas.toDataURL()метод, который получаетtypeа такжеencoderOptionsДва необязательных параметра.

вtypeУказывает формат изображения, по умолчаниюimage/png. а такжеencoderOptionsИспользуется для обозначения качества изображения в указанном формате изображения.image/jpegилиimage/webpВ случае качество изображения можно выбрать в диапазоне от 0 до 1. Если оно превышает диапазон значений, будет использоваться значение по умолчанию.0.92, другие параметры игнорируются.

Давайте посмотрим, как добиться сжатия изображения:

// compress.js
const MAX_WIDTH = 800; // 图片最大宽度

function compress(base64, quality, mimeType) {
  let canvas = document.createElement("canvas");
  let img = document.createElement("img");
  img.crossOrigin = "anonymous";
  return new Promise((resolve, reject) => {
    img.src = base64;
    img.onload = () => {
      let targetWidth, targetHeight;
      if (img.width > MAX_WIDTH) {
        targetWidth = MAX_WIDTH;
        targetHeight = (img.height * MAX_WIDTH) / img.width;
      } else {
        targetWidth = img.width;
        targetHeight = img.height;
      }
      canvas.width = targetWidth;
      canvas.height = targetHeight;
      let ctx = canvas.getContext("2d");
      ctx.clearRect(0, 0, targetWidth, targetHeight); // 清除画布
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
      let imageData = canvas.toDataURL(mimeType, quality / 100);
      resolve(imageData);
    };
  });
}

Для возвращаемых данных изображения в формате Data URL, чтобы еще больше уменьшить объем передаваемых данных, мы можем преобразовать их в объект Blob:

function dataUrlToBlob(base64, mimeType) {
  let bytes = window.atob(base64.split(",")[1]);
  let ab = new ArrayBuffer(bytes.length);
  let ia = new Uint8Array(ab);
  for (let i = 0; i < bytes.length; i++) {
    ia[i] = bytes.charCodeAt(i);
  }
  return new Blob([ab], { type: mimeType });
}

После завершения преобразования мы можем инкапсулировать объект Blob, соответствующий сжатому изображению, в объект FormData, а затем отправить его на сервер через AJAX:

function uploadFile(url, blob) {
  let formData = new FormData();
  let request = new XMLHttpRequest();
  formData.append("image", blob);
  request.open("POST", url, true);
  request.send(formData);
}

На самом деле объект Canvas предоставляет в дополнение кtoDataURL()метод, он также обеспечиваетtoBlob()метод, синтаксис этого метода следующий:

canvas.toBlob(callback, mimeType, qualityArgument)

а такжеtoDataURL()По сравнению с методом,toBlob()Метод асинхронный, поэтомуcallbackпараметр, этоcallbackПервый параметр метода обратного вызова по умолчанию — преобразованный.blobинформация о файле.

После введения вышеизложенного давайте взглянем на полный пример локального сжатия изображения:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>本地图片压缩</title>
  </head>
  <body>
    <input type="file" accept="image/*" onchange="loadFile(event)" />
    <script src="./compress.js"></script>
    <script>
      const loadFile = function (event) {
        const reader = new FileReader();
        reader.onload = async function () {
          let compressedDataURL = await compress(
            reader.result,
            90,
            "image/jpeg"
          );
          let compressedImageBlob = dataUrlToBlob(compressedDataURL);
          uploadFile("https://httpbin.org/post", compressedImageBlob);
        };
        reader.readAsDataURL(event.target.files[0]);
      };
    </script>
  </body>
</html>

В-четвертых, как выполнять кодирование и декодирование base64

В JavaScript две функции используются для декодирования и кодирования строк base64 соответственно:

  • btoa(): эта функция создает строку ASCII в кодировке base64 на основе «строки» двоичных данных.
  • atob(): эта функция способна декодировать строковые данные в кодировке base64.

4.1 Пример использования btoa

const name = 'Semlinker';
const encodedName = btoa(name);
console.log(encodedName); // U2VtbGlua2Vy

4.2 Пример использования atob

const encodedName = 'U2VtbGlua2Vy';
const name = atob(encodedName);
console.log(name); // Semlinker

Для двух методов atob и btoa a представляет ASCII, а b представляет Blob, который является двоичным. Таким образом, atob означает преобразование ASCII в двоичный код, что соответствует операции декодирования. А btoa представляет двоичный код в ASCII, что соответствует операции кодирования. Поняв значения a и b в методе, мы не будем использовать их неправильно в дальнейшей работе.

V. Резюме

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

6. Справочные ресурсы