preface

This article in the way of graphic and text in simple binary concept, the previous concept description is more boring, but very important! Hope everyone patience to look down, there is a surprise behind, will let you tiger body a shock ~😉

Blob

Blob represents a large object of binary type, usually a video, sound, or multimedia file, and in javaScript a Blob represents an immutable, raw data-like file object.

Its constructors are as follows:

new Blob(blobParts, options);
Copy the code
  • lobParts: An array type that can hold any number of arraysArrayBuffer.ArrayBufferView.BloborDOMString(encoded as UTF-8), concatenating them to form the data of the Blob object.
  • options: Optional, used to set the properties of the BLOb object. You can specify the following two properties:
    • Type: stores the contents of the array in the BLOBMIMEType (default “”).
    • Endings: Used to specify how the string containing the line end \n is written. A value ofnativeIndicates that the line terminator is changed to a newline suitable for the host operating system file system (the default istransparentIndicates that the terminator saved in the BLOB is kept unchanged.)
DOMString is a UTF-16 string. Because JavaScript already uses such strings, DOMString maps directly to a String.Copy the code
ArrayBuffer (binary data buffer), ArrayBufferView (Array-like view of binary data buffer)Copy the code

The following is an example 👇

  1. Create a BLOB object that contains a DomString object
    const blob = new Blob(['<div>john</div>'] and {type: 'text/xml' });
    console.log(blob); // Blob {size: 15, type: "text/xml"}
Copy the code
  1. Creates a BLOB object that contains an ArrayBuffer object
    var abf = new ArrayBuffer(8);
    const blob = new Blob([abf], { type: 'text/plain' });
    console.log(blob); // Blob {size: 8, type: "text/plain"}
Copy the code
  1. Create a BLOB object that contains an ArrayBufferView object
    var abf = new ArrayBuffer(8);
    var abv = new Int16Array(abf);
    const blob = new Blob(abv, { type: 'text/plain' });
    console.log(blob); // Blob {size: 4, type: "text/plain"}
Copy the code

attribute

Blob objects have two properties, as shown in the following table 👇 :

The property name describe
size The size of the data contained in the Blob object. The unit is byte. Read-only.
type A string indicating the MIME type of the data contained in the Blob object. If the type is unknown, the value is an empty string. Read-only.

methods

  • slice(start:number, end:number, contentType:DOMString): array-likesliceMethod that splits the original Blob object into a new Blob object in the specified range and returns it, which can be used for slice upload
    • Start: starts the index. The default value is 0
    • End: indicates the end index. The default value is the last index
    • ContentType: The MIME type of the new Blob, which is an empty string by default
  • stream(): returns an object that can read bloB contentsReadableStream.
  • text(): Returns aPromiseObject in UTF-8 format that contains all the contents of the BLOBUSVString.
  • arrayBuffer(): Returns aPromiseObject and contains all the contents of the BLOB in binary formatArrayBuffer.

Save the BLOB (or file) binary to formData for web requests (imageUrl, which can then fetch images, can be used for image presentation or later to send image addresses via webSocket)

File

A File object is a special Blob object that inherits all Blob properties and methods, but can also be used as a formData binary File upload

Obtain File:

Here we use input and drag and drop to select multiple images respectively 👇:

  • Input Gets the local file
  <input type="file" multiple id="f" />
  <script>var elem = document.getElementById('f'); elem.onchange = function (event) { var files = event.target.files; console.log(files); / / /{{name: "1.jpg",lastModified: 1594369580771. },{name:'2.jpg',lastModified: 1596012406708. }] var file = files[0]; console.log(file); // {name: "1.jpg",lastModified: 1594369580771,size: 22344,type: "image/jpeg". } console.log(file instanceof File); //true
      console.log(files instanceof FileList); // true/* File inherits Blob */ console.log(file.__proto__.__proto__); // Blob {size: 22344, type: ""}};</script>
Copy the code
  • Drag and drop to obtain
    <div id="content" ondrop="drop(event)" ondragover="allowDrop(event);" />
    <script>function allowDrop(ev) { ev.preventDefault(); } function drop(ev) { ev.preventDefault(); const files = ev.dataTransfer.files; console.log(files); / / /{{name: "1.jpg",lastModified: 1594369580771. },{name:'2.jpg',lastModified: 1596012406708. }] console.log(files instanceof FileList); // true
      }
    </script>
    <style type="text/css">
      #content {
        width: 500px;
        height: 500px;
        border: 1px solid brown;
      }
    </style>
    Copy the code

Add a multiple attribute to the input element to allow the user to select multiple files. Each file selected by the user is a file object. A FileList object is a list of these File objects.

attribute

File object properties, see the following table 👇 :

The property name describe
lastModified Reference file last modified date
name File name or file path
size Returns the size of the file in bytes
type The MIME type of the file

methods

File objects have no instance methods of their own, and since they inherit from Blob objects, they can use slice(), the instance method of Blob.

Data buffer

From XHR, File API, Canvas, etc., read a large string of byte streams. If you use Array in JS to store, it is wasteful and inefficient. In programming, a data buffer (or buffer for short) is a storage area in physical memory that manipulates binary data (faster than hard disk drive access) and is used to store temporary data as it is moved from one location to another. The interpreter reads rows with the help of the memory buffer that stores binary data. There is a running file in main memory, and if the interpreter had to return the file to read every bit, the execution would take a lot of time. To prevent this, JavaScript uses a data buffer that stores bits together and then sends them all together to the interpreter. This way, the JavaScript interpreter does not have to worry about retrieving files from file data. This approach saves execution time and speeds up the application. Various buffer classes perform valid binary operations on data, including File, Blob, ArrayBuffer, and Array. The method selected determines the internal structure of the buffer in memory.

Buffer

Buffers are objects provided by Node.js, not the front-end. A Buffer is similar to an array of integers, but it corresponds to a chunk of raw memory outside the V8 heap memory.

ArrayBuffer, ArrayBufferView

ArrayBuffer

An ArrayBuffer is a raw buffer of fixed-length binary data. Its purpose is to allocate a contiguous area of memory for storing data, so it is much faster than Array in JS for high-density access operations such as audio data. The purpose of an ArrayBuffer is to be written to memory in advance as a data source, so its length is fixed

Let’s take a look at what ArrayBuffer does:

The constructor of the ArrayBuffer object is as follows (length indicates the length of the ArrayBuffer)👇:

ArrayBuffer(length);
Copy the code

The difference between Array and ArrayBuffer 👇 :

Array ArrayBuffer
You can put numbers, strings, booleans, objects, arrays, and so on Only 0 and 1 binary data can be stored
The data is placed in the heap Data is placed on the stack, so fetching data is faster
You can add or subtract as you like Read-only, fixed size after initialization, whether the buffer is empty or not, can only be written with TypedArrays, Dataview

attribute

See the following table 👇 for the properties of the ArrayBuffer object:

The property name describe
byteLength Represents the size of an ArrayBuffer

methods

  • slice: takes two parameters 👉beginThat’s the beginning,endIndicates the end point. The ArrayBuffer () method returns a new ArrayBuffer whose contents are byte copies of the ArrayBuffer, from begin (included) to end (not included).

An ArrayBuffer cannot operate directly, but rather through TypedArray or DataView objects, which convert the data in the buffer into arrays of various data types and read and write the contents of the buffer in these formats. 👇

ArrayBufferView

Since an ArrayBuffer object doesn’t provide any way to read or write directly to memory, and an ArrayBufferView object is actually a view based on an ArrayBuffer object that specifies the basic processing unit for raw binary data, Read the contents of an ArrayBuffer object through an ArrayBufferView object. TypedArrays (TypedArrays) and dataviews are instances of ArrayBufferView.

TypedArrays

TypedArrays are a new concept in JavaScript designed to access raw binary data. TypedArrays are essentially the same as arraybuffers, except that they can read and write

The types of the array are: 👇 :

The name of the Size (in bytes) instructions
Int8Array 1 An 8-bit signed integer
Uint8Array 1 An 8-bit unsigned integer
Int16Array 2 16 – bit signed integer
Uint16Array 2 16 – bit unsigned integer
Int32Array 4 32 – bit signed integer
Uint32Array 4 32 – bit unsigned integer
Float32Array 4 32-bit floating point number
Float64Array 8 64-bit floating point number

Type conversion is shown in 👇 :Here are some code examples to show how to convert:

// Create an 8-byte ArrayBuffer
var b = new ArrayBuffer(8);  
  
// Create a view v1 that points to b, of type Int32, starting with the default byte index 0 and ending at the end of the buffer
var v1 = new Int32Array(b);  // Int32Array(2) [0, 0]
v1[0] = 1
console.log(v1); // Int32Array(2) [1, 0]
  
// Create a view v2 pointing to B, of type Uint8, starting with byte index 2 and ending at the end of the buffer
var v2 = new Uint8Array(b, 2);  // Uint8Array(6) [0, 0, 0, 0, 0, 0]
  
// Create a view v3 pointing to b, of type Int16, starting with byte index 2 and of length 2
var v3 = new Int16Array(b, 2.2);  // Int16Array(2) [0, 0]
Copy the code

Because normal Javascript arrays use a Hash lookup, typed arrays access fixed memory directly, so they’re faster than traditional arrays! At the same time, typed arrays naturally handle binary data, which is an inherent advantage for XMLHttpRequest, Canvas, webGL, and other technologies.

Fetch audio resources -> ArrayBuffer -> TypedArray -> Join into a TypedArray -> ArrayBuffer -> Blob -> Object URLCopy the code

DataView

DataView objects can read and store different types of binary data anywhere in the ArrayBuffer.

The syntax for creating DataView is as follows:

var dataView = new DataView(DataView(Buffer, byteOffset[optional], byteLength[optional]);Copy the code
attribute

The DataView object has three properties, as shown in the following table 👇 :

The property name describe
buffer Said ArrayBuffer
byteOffset Refers to the offset at the beginning of the buffer
byteLength Refers to the length of the buffer portion
methods
  • setint8()From:DataViewStores an 8-bit number (one byte) at the specified byte offset starting position.
  • getint8()From:DataViewGets an 8-bit number (one byte) at the specified byte offset starting position.

GetInt16, getUint16, getInt32, getUint32… Use method is consistent, here is not an example

Usage: 👇

let buffer = new ArrayBuffer(32);
let dataView = new DataView(buffer,0);
dataView.setInt16(1.56);
dataView.getInt16(1); / / 56
Copy the code

FileReader

The contents of blobs or file objects cannot be accessed directly, but if you want to read them and convert them into data in other formats, you can do so using the FileReader object API

  • readAsText(Blob): Converts blobs to text strings
  • readAsArrayBuffer(Blob): Converts bloBS to ArrayBuffer format data
  • readAsDataURL(): Converts Blob to Base64 format DataURL

Use the following 👇:

    const blob = new Blob(['<xml>foo</xml>'] and {type: 'text/xml' });
    console.log(blob); // Blob(14) {size: 14, type: "text/xml"}

    const reader = new FileReader();
    reader.onload = () = > {
      console.log(reader.result);
    };
    reader.readAsText(blob); // <xml>foo</xml>
    reader.readAsArrayBuffer(blob); // ArrayBuffer(14) {}
    reader.readAsDataURL(blob); // data:text/xml; base64,PHhtbD5mb288L3htbD4
Copy the code

Here we try to read the contents of a file as a string:

<input type="file" id='f' />
<script>
  document.getElementById('f').addEventListener('change'.function (e) {
    var file = this.files[0];
    // First, you need to create an instance of FileReader.
    const reader = new FileReader();
    reader.onload = function () {
        // Call back when the load is complete
        const content = reader.result;
        console.log(content);
    }
    reader.readAsText(file); // Convert the bloB to a text string to read
  }, false);
</script>
Copy the code

Read the following result 👇:

BlobURL

BlobURL (ObjectURL) is a pseudo protocol that can only be generated internally by browsers. We know that SRC attributes of script/img/video/iframe tags and background urls can be displayed by URL and base64. We can also convert bloBs or files to urls to generate bloburls to display images. BlobURL allows BLOBs and Files to be used as URL sources for images, downloading binary data links, and so on.

Image display 👇:

  <div id="content">
    <input type="file" multiple id="f" />
  </div>
  <script>
    const elem = document.getElementById('f');
    const content = document.getElementById('content');
    
    // Encapsulate a method to transform BlobUrl depending on the browser :file can be either a file object or a Blob object
    const getObjectURL = (file) = > {
      let url;
      if (window.createObjectURL) {
        url = window.createObjectURL(file);
      } else if (window.URL) {
        url = window.URL.createObjectURL(file);
      } else if (window.webkitURL) {
        url = window.webkitURL.createObjectURL(file);
      }
      return url;
    };

    elem.onchange = function (event) {
      const files = event.target.files;
      const file = files[0];
      const img = document.createElement('img');
      img.src = getObjectURL(file);
      content.appendChild(img);
    };
  </script>
Copy the code

When we look at the MM image element on the Demo page, we see that its URL address is neither a traditional HTTP nor a Base64 URL, but rather a blob: string that starts with the address bar and can be checked by placing it in the address bar.

File download 👇:

<body>
 <button onclick="download()">download.txt</button>

 <script>
      const getObjectURL = (file) = > {
        let url;
        if (window.createObjectURL) {
          url = window.createObjectURL(file);
        } else if (window.URL) {
          url = window.URL.createObjectURL(file);
        } else if (window.webkitURL) {
          url = window.webkitURL.createObjectURL(file);
        }
        return url;
      };
      function download() {
        const fileName = 'download.txt';
        const myBlob = new Blob(['johnYu'] and {type: 'text/plain' });
        downloadFun(fileName, myBlob);
      }
      function downloadFun(fileName, blob) {
        const link = document.createElement('a');
        link.href = getObjectURL(blob);
        link.download = fileName;
        link.click();
        link.remove();
        URL.revokeObjectURL(link.href);
      }
    </script>
  </body>
Copy the code

Click the button to download the document, which reads :johnYu

I’m not going to callrevokeObjectURLWhen visitingchrome://blob-internals/You can see a list of the current internal BLOb files:BlobUrl that is no longer used is automatically cleared later (as is closing the browser), but is best usedURL.revokeObjectURL(url)Remove them manually:

URL.revokeObjectURL('the blob: http://127.0.0.1:5500/d2a9a812-0dbf-41c5-a96b-b6384d33f281');
Copy the code

After execution, visit Chrome again ://blob-internals/ You can see that the file has been cleared

dataURL

DataURL allows content creators to embed smaller files into documents. This is similar to normal URL usage

The syntax format is 👇 :

data:[<mediatype>][;base64],data
Copy the code
  • data: prefix
  • mediatypeIndicates the data type, which is oneMIMEA string of type, such as image/ JPEG, representing a JPEG image file. If omitted, the default value istext/plain; charset=US-ASCII.
  • base64: flag bit (optional if text)
  • data: Data itself

How do I get the DataUrl

  1. The method used in the above example, readAsDataURL(), converts the Blob to Base64 DataUrl;
  2. Use nativeWeb APIEncoding/decoding

There are two functions in Javascript that encode and decode Base64 strings, atOB and BTOA. Both work only on the Data in the Data URL.

btoa('<xml>foo</xml>') // "PHhtbD5mb288L3htbD4="
atob('PHhtbD5mb288L3htbD4=') // "<xml>foo</xml>"
Copy the code
  • Atob (): Is responsible for decoding strings already encoded in Base64.
  • Btoa (): Converts the binary string to base64 encodedASCIIA string.
  1. Canvas toDataURL method:

Canvas provides a toDataURL method to get Canvas drawn content and convert it to Base64 format.

  <body>
    <canvas id="canvas" width="200" height="50"></canvas>
    <textarea id="content" style="width: 200px; height: 200px"></textarea>

    <script>
      var canvas = document.getElementById('canvas');
      if (canvas.getContext) {
        var ctx = canvas.getContext('2d');
        // Canvas drawing
        ctx.font = 'Bold 20px Arial';
        ctx.textAlign = 'left';
        ctx.fillStyle = 'purple';
        ctx.fillText('johnYu'.10.30);
        // Get the Data URL
        document.getElementById('content').value = canvas.toDataURL();
      }
    </script>
  </body>
Copy the code

As shown in the figure below, the content in the text box is the Base64 format of the content drawn on canvas.

If we return the previous resultdata:text/xml; base64,PHhtbD5mb288L3htbD4=In the browser address bar, you can see the displayed content.

The use of DataUrl

  1. Since it can be used as aURL substitute, DataURL and BlobUrl can be used in script/img/video/iframe tag SRC attributes and background urls. The usage is basically the same as BlobUrlelem.onchangeMake the following modifications
<body>
    <div id="content">
      <input type="file" multiple id="f" />
    </div>
    <script>
      const elem = document.getElementById('f');
      const content = document.getElementById('content');

      elem.onchange = function (event) {
        const files = event.target.files;
        const file = files[0];
        const img = document.createElement('img');
- img.src = getObjectURL(file);
+ const reader = new FileReader();
+ reader.onload = function () {
+ img.src = reader.result;
+};
+ reader.readAsDataURL(file);
        content.appendChild(img);
      };
    </script>
  </body>
Copy the code
  1. Because the data itself is represented by a URL, it can be stored in a Cookie and passed to the server.
  2. When the size of the image is too small to justify occupying an HTTP session.
  3. When access to external resources is cumbersome or limited
  4. Dataurls are not cached by browsers, but a small percentage are cached by CSS. In the following example, the use of dataurls is scenariospecific. It prevents the small background image from generating an HTTP request on its own, and the small image can be cached by the browser along with the CSS file and reused instead of being loaded every time it is used. As long as the image is not too large and not used repeatedly in CSS files, the DataUrl method can reduce page load times and improve the user’s browsing experience.
 background-image: url("data:image/gif; base64,R0lGODlhAwADAIAAAP///8zMzCH5BAAAAAAALAAAAAADAAMAAAIEBHIJBQA7"); 
Copy the code
  1. Use as a download connection
  <script>
    const createDownload = (fileName, content) = > {
      const blob = new Blob([content]);
      const reader = new FileReader();
      const link = document.createElement('a');
      link.innerHTML = fileName;
      link.download = fileName;
      reader.onload = () = > {
        link.href = reader.result;
        document.getElementsByTagName('body') [0].appendChild(link);
      };
      reader.readAsDataURL(blob);
    };

    createDownload('download.txt'.'johnYu');
  </script>
Copy the code

Click the a TAB and download the TXT file with the text content of johnYu. The BlobURL below can also be implemented 👇


The difference between

BlobURL is basically the same as DataUrl and can be checked by placing it in the address bar or used as a normal URL.

However, there are the following differences.

  1. BlobUrl is always a unique string, even if you pass the same Blob each time, a different BlobUrl will be generated each time; DataUrl values change with BLOB;
  2. As far as BlobUrl is concerned, it does not represent the data itself, the data is stored in the browser, and BlobUrl is just the key to access it. The data remains valid until the browser is closed or cleared manually. And the DataUrl is the directly encoded data itself. So even if you pass BlobUrl to a server and so on, you can’t access the data. Post DataUrl can still be accessed in the address bar after closing the browser, but BlobUrl cannot be accessed
  3. BlobUrl is generally short in length, but dataurls tend to be quite long because they store base64 encoded data directly from images (base64 encoded data is usually one-third larger than binary images). , so when it comes to explicit large images, using BlobUrl gives you better possibilities, speed and memory than DataUrl
  4. BlobUrl makes it easy to get source data using XMLHttpRequest (xhr.responseType = ‘blob’). For dataurls, not all browsers support XMLHttpRequest to retrieve source data
  <body>
    <button onclick="download1()">XMLHttpRequest download</button>
    <button onclick="download2()">The fetch download</button>
    <img id="img" />
    <script>
      var eleAppend = document.getElementById('forAppend');
      const url = 'https://sf3-ttcdn-tos.pstatp.com/img/user-avatar/9ecb4e119c26e64b8b4ec5258f159b3b~300x300.image';
      const pingan = document.querySelector('#pingan');
      function download1() {
        const xhr = new XMLHttpRequest();
        xhr.open('get', url, true);
        xhr.responseType = 'blob';
        xhr.onload = function () {
          if (this.status == 200) {
            renderImage(this.response); }}; xhr.send(null);
      }
      function download2() {
        fetch(url)
          .then((res) = > {
            return res.blob();
          })
          .then((myBlob) = > {
            renderImage(myBlob);
          });
      }

      function renderImage(blob) {
        window.URL = window.URL || window.webkitURL;
        var img = document.getElementById('img');
        img.onload = function (e) {
          window.URL.revokeObjectURL(img.src); // Clear release
        };
        img.src = window.URL.createObjectURL(blob);
      }
    </script>
  </body>
Copy the code
  1. BlobUrl can also be used as a web address for other resources, such as HTML files, JSON files, etc. To ensure that the browser can correctly parse the file type returned by BlobUrl, specify the corresponding type when creating the Blob object
    const createDownload = (fileName, content) = > {
      const blob = new Blob([content], { type: 'text/html' });
      const link = document.createElement('a');
      link.innerHTML = fileName;
      link.download = fileName;
      link.href = getObjectURL(blob);
      document.getElementsByTagName('body') [0].appendChild(link);
    };
    createDownload('download.html'.'<button>foo</button>');
Copy the code

6. Dataurls are not cached by browsers, which means they are downloaded every time such a page is visited. This is a matter of efficiency – especially when the image is used extensively throughout the site. But a small portion can be cached via CSS

canvas

The Canvas element is responsible for setting up a region on the page that you can then dynamically draw in using JavaScript.

methods

  • toDataURL(type, encoderOptions)): returns the DataUrl in the specified format. This method takes two optional arguments
    • Type: indicates the image format. The default value is image/ PNG
    • EncoderOptions: Indicates the quality of the image. If the image format is image/ JPEG or image/webp, the image quality can be selected from 0 to 1. If the value is outside the range, the default value of 0.92 will be used and other parameters will be ignored.
  • toBlob(callback, type, encoderOptions): Creates Blob objects that display canvas images. The default image type is Image/PNG and the resolution is96dpi
    • Callback: The argument is the callback function of the BLOb object
  • getImageData(x,y,width,height): Returns an ImageData object that copies the pixel data of the specified rectangle on the canvas.
    • X: the x-coordinate of the upper-left position where the replication begins.
    • Y: the y-coordinate of the upper-left position where the replication begins.
    • Width: Width of the rectangle area to be copied.
    • Height: The height of the rectangle region to be copied.
  • putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight): puts the ImageData (from the specified ImageData object) back on the canvas.
    • ImgData: Specifies the ImageData object to be put back into the canvas.
    • X: The x-coordinate of the upper-left corner of the ImageData object, in pixels.
    • Y: The y coordinate of the upper-left corner of the ImageData object, in pixels.
    • DirtyX: optional. Horizontal value (x), in pixels, the position of the image on the canvas.
    • DirtyY: optional. Horizontal value (y), in pixels, the position of the image on the canvas.
    • DirtyWidth: optional. The width used to draw the image on the canvas.
    • DirtyHeight: optional. The height used to draw the image on the canvas.

Application scenarios

When we need to obtain the content of canvas, we can use toDataURL and toBlob attributes (which can be used for signature, image clipping, image compression and other scenes). PutImageData and getImageData can be used for image grayscale or replication (see the following section of application scenarios 👇).

Get content:

<body>
    <div id="content">
      <button onclick="drawnImg()">The plot</button>
      <button onclick="getImg()">Access to images</button>
      <canvas style="border: 1px solid black" id="drawing" width="200" height="200">A drawing of something.</canvas>
      <img src="./timg.jpg" alt="" />
    </div>
    <script>
      var drawing = document.getElementById('drawing');
      var quality = 0.3;
      const imgType = 'image/jpeg';

      var drawnImg = function () {
        if (drawing.getContext) {
          var context = drawing.getContext('2d');
          // Get the image's data URI
          var image = document.images[0];
          context.drawImage(image, 20.20.100.100); }};var getImg = async function () {
        const content = getContent('base64');
        console.log(content);
        const content1 = await getContent('file');
        console.log(content1);
      };
      var getContent = function (type) {
        switch (type) {
          case 'base64':
            {
              const imgURL = drawing.toDataURL(imgType, quality);
              return imgURL;
            }
            break;
          case 'file':
            {
              // Convert to file format
              return new Promise((resolve) = > {
                drawing.toBlob(
                  (blob) = > {
                    resolve(blob);
                  },
                  imgType,
                  quality
                );
              });
            }
            break; }};</script>
  </body>
Copy the code

Relationship and transformation

String → Uint8Array

    var str = 'ab';
    console.log(Uint8Array.from(str.split(' '), (e) = > e.charCodeAt(0))); // Uint8Array(2) [97, 98]
Copy the code

Uint8Array → String

    var u8 = Uint8Array.of(97.98);
    console.log(Array.from(u8, (e) = > String.fromCharCode(e)).join(' ')); // ab
Copy the code

String → DataUrl

    var str = 'ab';
    console.log('data:application/octet-stream; base64,' + btoa(str)); // data:application/octet-stream; base64,YWI=
Copy the code

DataUrl -> string

    var data = 'data:application/octet-stream; base64,YWI=';
    console.log(atob(data.split(', ') [1])); // ab
Copy the code

Uint8Array -> ArrayBuffer

    var u8 = Uint8Array.of(1.2);
    console.log(u8.buffer); // ArrayBuffer(2) {}
Copy the code

ArrayBuffer -> Uint8Array

    var buffer = new ArrayBuffer(2);
    console.log(new Uint8Array(buffer)); // Uint8Array(2) [0, 0]
Copy the code

ArrayBuffer -> DataView

    var buffer = new ArrayBuffer(2);
    var dataView = new DataView(buffer, 0); // DataView(2) {}
Copy the code

DataView -> ArrayBuffer

    console.log(dataView.buffer); // ArrayBuffer(2) {}
Copy the code

ArrayBuffer – a Blob

    var buffer = new ArrayBuffer(32);
    var blob = new Blob([buffer]);  // Blob {size: 32, type: ""}
Copy the code

UintXXArray – a Blob

    var u8 = Uint8Array.of(97.32.72.101.108.108.111.32.119.111.114.108.100.33);
    var blob = new Blob([u8]);
Copy the code

String → Blob

    var blob = new Blob(['Hello World! '] and {type: 'text/plain'}); // Blob {size: 12, type: "text/plain"}
Copy the code

New Blob() to Blob

DataUrl -> blob

    var data = 'data:application/octet-stream; base64,YWI=';
    function dataURLtoBlob(dataurl) {
      var arr = dataurl.split(', '),
        mime = arr[0].match(/ : (. *?) ; /) [1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);

      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new Blob([u8arr], { type: mime });
    }
    console.log(dataURLtoBlob(data)); // Blob {size: 2, type: "application/octet-stream"}
Copy the code

The Blob –

The FileReader Api is used to convert readAsText(Blob), readAsArrayBuffer(Blob), and readAsDataURL(), but asynchronously

    var blob = new Blob(['a Hello world! '] and {type: 'text/plain' });
    var reader = new FileReader();
    reader.readAsText(blob, 'utf-8');
    reader.onload = function (e) {
      console.info(reader.result); // a Hello world!
    };
    reader.onerror = function (e) {
      console.error(reader.error);
    };
Copy the code

You can use promises to do multiple conversions

    var blob = new Blob(['a Hello world! '] and {type: 'text/plain' });
    function read(blob) {
      var fr = new FileReader();
      var pr = new Promise((resolve, reject) = > {
        fr.onload = (eve) = > {
          resolve(fr.result);
        };
        fr.onerror = (eve) = > {
          reject(fr.error);
        };
      });

      return {
        arrayBuffer() {
          fr.readAsArrayBuffer(blob);
          return pr;
        },
        binaryString() {
          fr.readAsBinaryString(blob);
          return pr;
        },
        dataURL() {
          fr.readAsDataURL(blob);
          return pr;
        },
        text() {
          fr.readAsText(blob);
          returnpr; }}; }var pstr1 = read(blob).binaryString();
    var pstr2 = read(blob)
      .arrayBuffer()
      .then((e) = > Array.from(new Uint8Array(e), (e) = > String.fromCharCode(e)).join(' '));
    Promise.all([pstr1, pstr2]).then((e) = > {
      console.log(e[0]); // a Hello world!
      console.log(e[0] === e[1]); // true
    });
Copy the code

Application scenarios

Image graying

This is mainly used to convert canvas and imageData

<body>
    <button onclick="drawngray()">Black and white images</button>
    <img src="./syz.jpg" alt="" />
    <canvas id="myCanvas">canvas</canvas>
    <script>
      var drawngray = function () {
        var myCanvas = document.getElementById('myCanvas');
        if (myCanvas.getContext) {
          var context = myCanvas.getContext('2d');
          var image = document.images[0];
          // Dynamically set the canvas size
          myCanvas.width = image.width;
          myCanvas.height = image.height;
          var imageData, data, i, len, average, red, green, blue, alpha;
          // Draw the original image
          context.drawImage(image, 0.0);
          // get image data
          imageData = context.getImageData(0.0, image.width, image.height);
          data = imageData.data;
          for (i = 0, len = data.length; i < len; i += 4) {
            red = data[i];
            green = data[i + 1];
            blue = data[i + 2];
            // alpha = data[i + 3];
            // Find the RGB average value
            average = Math.floor((red + green + blue) / 3);
            // Set the color value, opacity unchanged
            data[i] = average;
            data[i + 1] = average;
            data[i + 2] = average;
          }

          // Write back image data and display results
          imageData.data = data;
          context.putImageData(imageData, 0.0); }};</script>
  </body>
Copy the code

The getImageData except time and putImageData can also be used as a cavas photo copy: https://www.w3school.com.cn/tiy/t.asp?f=html5_canvas_getimagedataCopy the code

Image compression

To achieve image compression in the front end, we can use the toDataURL() method provided by the Canvas object

compress.js

const MAX_WIDTH = 800; // Maximum width of 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 = () = > {
      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);
      // Base64 compressed by toDataURL
      let imageData = canvas.toDataURL(mimeType, quality / 100);
      resolve(imageData);
    };
  });
}
Copy the code

test.html

  <body>
    <input type="file" accept="image/*" onchange="loadFile(event)" />
    <script src="./compress.js"></script>
    <script>
      function dataUrlToBlob(base64) {
        var arr = base64.split(', '),
          mime = arr[0].match(/ : (. *?) ; /) [1],
          bstr = atob(arr[1]),
          n = bstr.length,
          u8arr = new Uint8Array(n);

        while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
        }
        return new Blob([u8arr], { type: mime });
      }

      function uploadFile(url, blob) {
        let formData = new FormData();
        let request = new XMLHttpRequest();
        // Encapsulate to FormData for file upload
        formData.append('image', blob);
        request.open('POST', url, true);
        request.send(formData);
      }

      const loadFile = function (event) {
        const reader = new FileReader();
        reader.onload = async function () {
          let compressedDataURL = await compress(reader.result, 90.'image/jpeg');
          // Convert base64 into Blob objects after compression to reduce the amount of data transferred
          let compressedImageBlob = dataUrlToBlob(compressedDataURL);
          uploadFile('https://httpbin.org/post', compressedImageBlob);
        };
        // Get the image file selected by the user and convert it to base64 by FileReader
        reader.readAsDataURL(event.target.files[0]);
      };
    </script>
  </body>
Copy the code

Shard to upload

<body>
    <input type="file" name="file" onchange="selfile();" />

    <script>
      const url = 'https://httpbin.org/post';
      / * * *@param File Original file *@param ChunkSize Default size of each uploaded fragment */
      async function chunkedUpload(file, chunkSize = 1024 * 1024 * 5) {
        // Split the file into chunkSize chunks and upload only the chunkSize chunks per request
        for (let start = 0; start < file.size; start += chunkSize) {
          // File objects inherit from Blob objects, so large files can be sliced using the slice method
          const chunk = file.slice(start, start + chunkSize + 1);
          const fd = new FormData();
          fd.append('data', chunk);

          await fetch(url, { method: 'post'.body: fd })
            .then((res) = > res.text())
            .then((res) = > console.log(res)); // Prints the upload result}}function selfile() {
        let file = document.querySelector('[name=file]').files[0];

        // Customize the fragment size
        const LENGTH = 1024 * 1024 * 1;
        chunkedUpload(file, LENGTH);
      }
    </script>
  </body>
Copy the code

After the server receives these slices, it can concatenate them. Here is an example of PHP concatenating slices:

$filename = './upload/' . $_POST['filename'];// Determine the file name for the upload
// If there is no file in the first upload, create a file. After uploading, just append data to this file
if(! file_exists($filename)){ move_uploaded_file($_FILES['file'] ['tmp_name'],$filename);
}else{
    file_put_contents($filename,file_get_contents($_FILES['file'] ['tmp_name']),FILE_APPEND);
    echo $filename;
}
Copy the code

Remember to modify the server configuration of nginx when testing, otherwise Large files may prompt 413 Request Entity Too Large error.

server {
	// ...
	client_max_body_size 50m;
}
Copy the code

Refer to the article 📜

❤️ Understand DOMString, Document, FormData, Blob, File, and ArrayBuffer data types

❤️ Talk about the binary family of JS: Blob, ArrayBuffer and Buffer

❤️ Blob you don’t know

Extension 🏆

If you find this article helpful, check out my other articles at ❤️ :

Introductory notes | fast 🚀 👍 vue3 practical experience

👍 10 simple tips to make your vue.js code more elegant 🍊

👍 Close contact with websocket🚀

👍 5 Design patterns to know for Web development

👍 Data structures Web development should know about

👍 How do I get screen, window and web page sizes in JavaScript