美文网首页
谈谈前端二进制

谈谈前端二进制

作者: 莣忧草_3b53 | 来源:发表于2020-07-23 23:26 被阅读0次

    整个文章围绕前端如何进行图片处理,然后穿插介绍二进制、Blob、Blob URL、Base64、Data URL、ArrayBuffer、TypedArray、DataView 和图片压缩相关的知识点。

    一、 「选择本地图片 -> 图片预览」

    1.1 FileReader API

    在支持 FileReader API 的浏览器中,我们也可以利用该 API 方便实现图片本地预览功能。


    image.png
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>图片本地预览示例</title>
      </head>
      <body>
        <h3>阿宝哥:图片本地预览示例</h3>
        <input type="file" accept="image/*" onchange="loadFile(event)" />
        <img id="previewContainer" />
    
        <script>
          const loadFile = function (event) {
            const reader = new FileReader();
            reader.onload = function () {
              const output = document.querySelector("#previewContainer");
              output.src = reader.result;
            };
            reader.readAsDataURL(event.target.files[0]);
          };
        </script>
      </body>
    </html>
    

    FileReader的一些API:
    https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader

    我们可以在 Elements 面板中看到 Data URL 的 数据:


    image.png

    这串奇怪的字符串被称为 Data URL,它由四个部分组成:前缀(data:)、指示数据类型的 MIME 类型、如果非文本则为可选的 base64 标记、数据本身:

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

    mediatype 是个 MIME 类型的字符串参考:https://www.w3school.com.cn/media/media_mimeref.asp

    在 Web 项目开发过程中,为了减少 HTTP 请求的数量,对应一些较小的图标,我们通常会考虑使用 Data URL 的形式内嵌到 HTML 或 CSS 文件中。「但需要注意的是:如果图片较大,图片的色彩层次比较丰富,则不适合使用这种方式,因为该图片经过 base64 编码后的字符串非常大,会明显增大 HTML 页面的大小,从而影响加载速度。」

    1.2 Base64

    「Base64」 是一种基于 64 个可打印字符来表示二进制数据的表示方法。2^6=64,6个位标识一个字符。3个字节3*8=24。标识4个base64的字符。

    「Base64 常用于在处理文本数据的场合,表示、传输、存储一些二进制数据,包括 MIME 的电子邮件及 XML 的一些复杂数据。」

    在 JavaScript 中,有两个函数被分别用来处理解码和编码 base64 字符串:

    1. btoa():该函数能够基于二进制数据 “字符串” 创建一个 base64 编码的 ASCII 字符串。
    2. atob():该函数能够解码通过 base64 编码的字符串数据。

    需要注意的是 base64 只是一种数据编码方式,目的是为了保障数据的安全传输。但标准的 base64 编码无需额外的信息,即可以进行解码,是完全可逆的。因此在涉及传输私密数据时,并不能直接使用 base64 编码,而是要使用专门的对称或非对称加密算法。

    二、网络下载图片 -> 图片预览

    除了可以从本地获取图片之外,我们也可以使用 fetch API 从网络上获取图片,然后在进行图片预览。当然对于网络上可正常访问的图片地址,我们可以直接把地址赋给 img 元素,但是有的图片加密了,因为我们需要在 Web Worker 中使用 fetch API 获取图片数据并进行解密操作。


    image.png
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>获取远程图片预览示例</title>
      </head>
      <body>
        <h3>阿宝哥:获取远程图片预览示例</h3>
        <img id="previewContainer" style="width: 50%;"/>
    
        <script>
          const image = document.querySelector("#previewContainer");
          fetch("https://avatars1.githubusercontent.com/u/11811888?s=400&u=2d330564df93a5291ea8f261c588670ae01f20de&v=4")
            .then((response) => response.blob())
            .then((blob) => {
              const objectURL = URL.createObjectURL(blob);
              image.src = objectURL;
            });
        </script>
      </body>
    </html>
    
    image.png

    以上的特殊字符串,我们称之为 「Object URL」,相比前面介绍的 Data URL,它简洁很多。接下来我们来认识一下 Object URL 这种协议。

    2.1 Object URL

    Object URL 是一种伪协议,也被称为 Blob URL。它允许 Blob 或 File 对象用作图像,下载二进制数据链接等的 URL 源。 在浏览器中,我们使用 URL.createObjectURL 方法来创建 Blob URL,该方法接收一个 Blob 对象,并为其创建一个唯一的 URL,其形式为 blob:<origin>/<uuid>,对应的示例如下:

    blob:https://example.org/40a5fb5a-d56d-4a33-b4e2-0acf6a8e5f641
    

    浏览器内部为每个通过 URL.createObjectURL 生成的 URL 存储了一个 「URL → Blob」 映射。因此,此类 URL 较短,但可以访问 Blob。生成的 URL 仅在当前文档打开的状态下才有效。但如果你访问的 Blob URL 不再存在,则会从浏览器中收到 404 错误。

    上述的 Blob URL 看似很不错,但实际上它也有副作用。虽然存储了 URL → Blob 的映射,但 Blob 本身仍驻留在内存中,浏览器无法释放它。映射在文档卸载时自动清除,因此 Blob 对象随后被释放。但是,如果应用程序寿命很长,那不会很快发生。因此,如果我们创建一个 Blob URL,即使不再需要该 Blob,它也会存在内存中。

    针对这个问题,我们可以调用 URL.revokeObjectURL(url) 方法,从内部映射中删除引用,从而允许删除 Blob(如果没有其他引用),并释放内存。

    既然讲到了 Blob URL,不得不提 Blob。那么什么是 Blob 呢?我们继续往下看。

    2.2 Blob API

    Blob(Binary Large Object)表示二进制类型的大对象。在数据库管理系统中,将二进制数据存储为一个单一个体的集合。Blob 通常是影像、声音或多媒体文件。「在 JavaScript 中 Blob 类型的对象表示不可变的类似文件对象的原始数据。」

    image.png

    myBlob 对象含有两个属性:size 和 type。其中 size 属性用于表示数据的大小(以字节为单位),type 是 MIME 类型的字符串。Blob 表示的不一定是 JavaScript 原生格式的数据。比如 File 接口基于 Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。

    Blob 由一个可选的字符串 type(通常是 MIME 类型)和 blobParts 组成:

    image.png
    2.2.1 Blob 构造函数

    Blob 构造函数的语法为:

    var aBlob = new Blob(blobParts, options);
    
    1. blobParts:它是一个由 ArrayBuffer,ArrayBufferView,Blob,DOMString 等对象构成的数组。DOMStrings 会被编码为 UTF-8。
    2. options:一个可选的对象,包含以下两个属性:
      2.1 type —— 默认值为 "",它代表了将会被放入到 blob 中的数组内容的 MIME 类型。
      2.2 endings —— 默认值为 "transparent",用于指定包含行结束符 \n 的字符串如 何被写入。它是以下两个值中的一个:"native",代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 "transparent",代表会保持 blob 中保存的结束符不变。
    let myBlobParts = ['<html><h2>Hello Semlinker</h2></html>']; // an array consisting of a single DOMString
    let myBlob = new Blob(myBlobParts, {type : 'text/html', endings: "transparent"}); // the blob
    
    console.log(myBlob.size + " bytes size");
    // Output: 37 bytes size
    console.log(myBlob.type + " is the type");
    // Output: text/html is the type
    
    
    let hello = new Uint8Array([72, 101, 108, 108, 111]); // 二进制格式的 "hello"
    let blob = new Blob([hello, ' ', 'semlinker'], {type: 'text/plain'});
    

    介绍完 Blob 构造函数,接下来我们来分别介绍 Blob 类的属性和方法:

    image.png
    2.2.2 Blob 属性

    前面我们已经知道 Blob 对象包含两个属性:

    1. size(只读):表示 Blob 对象中所包含数据的大小(以字节为单位)。
    2. type(只读):一个字符串,表明该 Blob 对象所包含数据的 MIME 类型。如果类型未知,则该值为空字符串。
    2.2.3 Blob 方法
    1. slice([start[, end[, contentType]]]):返回一个新的 Blob 对象,包含了源 Blob 对象中指定范围内的数据。
    2. stream():返回一个能读取 blob 内容的 ReadableStream。
    3. text():返回一个 Promise 对象且包含 blob 所有内容的 UTF-8 格式的 USVString。
    4. arrayBuffer():返回一个 Promise 对象且包含 blob 所有内容的二进制格式的 ArrayBuffer。

    「Blob 对象是不可改变的」。我们不能直接在一个 Blob 中更改数据,但是我们可以对一个 Blob 进行分割,从其中创建新的 Blob 对象,将它们混合到一个新的 Blob 中。这种行为类似于 JavaScript 字符串:我们无法更改字符串中的字符,但可以创建新的更正后的字符串。

    对于 fetch API 的 Response 对象来说,该对象除了提供 blob() 方法之外,还提供了 json()、 text() 、formData() 和 arrayBuffer() 等方法,用于把响应转换为不同的数据格式。

    对于前面的示例,我们把响应对象转换为 ArrayBuffer 对象,同样可以正常显示从网络下载的图像,具体的代码如下所示:

    <h3>阿宝哥:获取远程图片预览示例</h3>
    <img id="previewContainer" style="width: 50%;"/>
    
    <script>
       const image = document.querySelector("#previewContainer");
       fetch("https://avatars3.githubusercontent.com/u/4220799")
         .then((response) => response.arrayBuffer())
         .then((buffer) => {
            const blob = new Blob([buffer]);
            const objectURL = URL.createObjectURL(blob);
            image.src = objectURL;
       });
    </script>
    

    转载:https://mp.weixin.qq.com/s/DoipkAca00MuXon8wRYPgQ

    相关文章

      网友评论

          本文标题:谈谈前端二进制

          本文链接:https://www.haomeiwen.com/subject/keyclktx.html