Why use Base64

We know that a byte ranges from 0 to 255 (hexadecimal: 0x00 to 0xFF), where the ASCII value ranges from 0 to 127 (hexadecimal: 0x00 to 0x7F). Values between 128 and 255 (hexadecimal: 0x80 to 0xFF) beyond the ASCII range are invisible characters.

The American Standard Code for Information Interchange (ASCII) is a computer coding system based on the Latin alphabet. It is primarily used to display modern English, while an extended version of the Extended American Standard Information Interchange Code can partially support other Western European languages and is equivalent to the international standard ISO/IEC 646.

In THE ASCII code 0-31 and 127 are the control characters, a total of 33. Here are some of the control characters:

The remaining 95, 32-126, are printable characters, including numbers, upper and lower case letters, common symbols, and so on.

When invisible characters are transmitted on the network, for example, from computer A to computer B, they usually have to go through multiple routing devices. Because different devices process characters differently, those invisible characters may be processed incorrectly, which is not good for transmission. To solve this problem, we can first encode the data, such as base64 encoding, into visible characters, i.e., visible characters that can be represented by ASCII codes, thus ensuring reliable transmission of the data. Base64 consists of exactly 64 characters, including 0 to 9, a to z, a to z, +, /, which are part of the 95 visible characters in the ASCII representable range.

What is Base64

Base64 is a representation of binary data based on 64 printable characters. Since 2⁶ = 64, every 6 bits is a unit corresponding to a printable character. Three bytes have 24 bits, corresponding to four Base64 cells, that is, three bytes can be represented by four printable characters. The corresponding transformation process is shown in the figure below:

**Base64 is used to represent, transmit, and store binary data in the context of text data, including MIME E-mail and complex data in XML. ** In MIME E-mail, Base64 can be used to encode binary byte sequence data into ASCII character sequence text. When used, base64 is specified in the transport encoding. The characters used include 26 upper and lower Latin letters, 10 digits, plus sign (+), and slash (/), a total of 64 characters, and the equal sign (=) is used as a suffix. The corresponding index table for Base64 is as follows:

After understanding the above knowledge, let’s take encoding a Man string as an example, to intuitively feel the coding process. Man consists of M, a, and n. The corresponding ASCII codes are 77, 97, and 110.

Next, base64 encoding is performed with every 6 bits as a unit, as shown in the figure below:

As can be seen from the figure, the result of Man (3 bytes) encoding is TWFu (4 bytes), and it is obvious that the volume will increase by 1/3 after base64 encoding. The string Man is exactly 3 in length, which can be represented by four base64 units. But what if the length of the string to be encoded is not an integer multiple of 3?

If the number of bytes to be encoded is not divisible by 3 and ends up being one or two bytes too many, you can handle this using the following method: First make it divisible by 3 with a 0 byte value at the end and then base64 encoding.

Taking encoding character A as an example, its number of bytes is 1, which cannot be divisible by 3, and it needs to complement 2 bytes, as shown in the figure below:

As you can see from the figure above, the result of the base64 encoding of the character A is QQ==, and the two = after this result represent the number of complementary bytes. The last block of 1 base64 bytes has 4 bits of 0.

Let’s take another example. Let’s assume that the string to be encoded is BC, its number of bytes is 2, it is not divisible by 3, and it needs to complement 1 byte, as shown in the figure below:

As you can see from the figure above, the base64 encoded result of the string BC is QkM=, and the 1 = after the result represents the number of complementary bytes. The last block of 1 base64 bytes has 2 bits of 0.

Application of Base64 encoding

3.1 Displaying base64 encoded Images

When writing HTML pages, for some simple images, it is usually chosen to embed the image content directly in the page, so as to reduce unnecessary network requests, but the image data is binary data, how to embed? Most modern browsers support a feature called Data URLs, which allows you to use Base64 to encode binary Data from an image or other file and embed it as a text string inside a Web page.

Data URLs consist of four parts: a prefix (Data:), a MIME type indicating the Data type, optional Base64 markup if it’s not text, and the Data itself:

data:[<mediatype>][;base64],<data>
Copy the code

Mediatype is a string of MIME type, such as “image/jpeg” for a JPEG image file. If omitted, the default value is text/plain; Charset = US – ASCII. If the data is of text type, you can embed the text directly (using the appropriate entity or escape characters, depending on the document type). For binary data, you can base64 encode the data and then embed it. Like embedding an image:

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

Multipurpose Internet Mail Extensions (MIME) Enables a file with a certain extension to be opened by an application. When the file is accessed, the browser automatically opens the file using the specified application. Used to specify some custom client file names, and some media file opening methods.

HTML text/ HTML, PNG image. PNG image/ PNG, and TXT text/plain are common MIME types.

Note, however, that if the image is large and has a rich color hierarchy, it is not appropriate to use this method, because the large base64-encoded string of the image will significantly increase the size of the HTML page, which will affect the loading speed. In addition, using HTML FileReader API, we can also facilitate the realization of local image preview function, the specific code is as follows:

<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>
Copy the code

After previewing the image locally, you can submit the Data to the Data URLs of the image directly to the server. In this case, the server needs to do some related processing to save the uploaded pictures normally. Here take Express as an example, and the specific processing code is as follows:

const app = require('express') (); app.post('/upload'.function(req, res){
    let imgData = req.body.imgData; // Get the base64 image data in the POST request
    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("Picture uploaded successfully!"); }}); });Copy the code

3.2 Image Compression in the Browser

In some cases, you might want to reduce the amount of data transferred when uploading a local image by compressing it before submitting it to the server. To compress images on the front end, we can use the Canvas object’s toDataURL() method, which takes two optional parameters, Type and encoderOptions.

Type indicates the image format, which is image/ PNG by default. EncoderOptions is used to indicate the image quality, which can be selected from 0 to 1 if the image format is specified as Image/JPEG or Image /webp. If the value is out of range, the default value of 0.92 will be used and other parameters will be ignored.

Let’s take a look at how to achieve specific image compression:

// compress.js
const MAX_WIDTH = 800; // The maximum width of the image

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 = (a)= > {
      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); // Clear the canvas
      ctx.drawImage(img, 0.0, canvas.width, canvas.height);
      let imageData = canvas.toDataURL(mimeType, quality / 100);
      resolve(imageData);
    };
  });
}
Copy the code

For the image Data returned in the Data URL format, to further reduce the amount of Data transferred, we can convert it to a Blob object:

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 });
}
Copy the code

After the transformation is complete, we can wrap the Blob object of the compressed image in the FormData object and submit it to the server via 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);
}
Copy the code

In addition to the toDataURL() method, the Canvas object also provides a toBlob() method, which has the following syntax:

canvas.toBlob(callback, mimeType, qualityArgument)
Copy the code

The toBlob() method is asynchronous compared to the toDataURL() method, so it has an additional callback parameter. The first parameter of this callback method is the converted blob file information by default.

With that said, let’s look at a complete example of local image compression:


      
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
    <title>Local image compression</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>
Copy the code

How to encode and decode base64

In JavaScript, there are two functions used to handle decoding and encoding base64 strings, respectively:

  • Btoa () : This function creates a Base64 encoded ASCII string based on binary data “strings”.
  • Atob () : This function decodes base64 encoded string data.

4.1 BTOA Example

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

4.2 AtOB Example

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

For the atOB and BTOA methods, a stands for ASCII and B stands for Blob, or binary. Thus ATOB stands for ASCII to binary, which corresponds to the decoding operation. Btoa stands for binary to ASCII, which corresponds to the encoding operation. After understanding the meaning of a and B respectively in the method, we will not make mistakes in the future work.

Five, the summary

Base64 is a data encoding method designed to ensure secure data transmission. But standard Base64 encoding requires no additional information, that is, it can be decoded and is completely reversible. Therefore, when it comes to transmitting private data, instead of using base64 encoding directly, specialized symmetric or asymmetric encryption algorithms are used.

6. Reference Resources

  • Wikipedia – Base64
  • Principles and applications of Base64 encoding
  • Zhihu – Why use Base64 encoding and what are the situational requirements?