前端系列之:Blob

06-01 1027阅读

Blob 与二进制

什么是二进制?

二进制是计算机数据的基本表示形式,只使用 0 和 1 两个数字来表示数值。任何类型的数据(无论是文本、图片、音频文件等)都可以通过二进制表示。

什么是 Blob?

全称 Binary Large Object,二进制类型的大对象。是一种数据类型,用来存储二进制数据。

怎么解释 JavaScript 的数据类型中并没有 Blob 类型?

Blob 是用来存储二进制数据的,而二进制又是计算机的基本表示形式,所以很多编程语言(如 java)和数据库(如 mysql)都是支持 Blobl 的。

但对于前端 Blob 而言,Blob 是由浏览器环境(或类浏览器环境,如 WebView 或 React Native)提供的,而不是 JavaScript 语言本身的一部分。Blob 是 Web API 的一部分,用于表示不可变的二进制数据。所以 Blob 对象只有在浏览器环境中才能正常使用。如果在非浏览器环境(如 Node.js 环境)中,默认情况下是没有 Blob 对象的。

Blob 表示不可变的、原始的二进制数据。这句话怎么理解?

“不可变” 表示一旦 Blob 对象被创建,其内容就不能被修改。如果你需要修改 Blob 中的数据,通常的做法是创建一个新的 Blob 对象,而不是直接更改原始的 Blob 对象。

Blob 用途

  • 数据库:在数据库中,Blob 用来存储图像、音频文件等二进制数据。例如,关系型数据库中的 BLOB 类型字段用来保存图像或其他多媒体文件。

  • 文件存储:Blob 通常用于大文件(如视频、音频、图像等)的存储,并且通常以二进制格式存在。

  • Web 开发(本文重点):

    • 上传文件到服务器。

    • 从服务器下载文件。

    • 在浏览器中生成文件并下载。

    • 处理图片、视频等二进制数据。

      Blob 构造函数

      要从其他非 Blob 对象和数据构造一个 Blob,需要使用 Blob() 构造函数。Blob 对象一旦创建,其内容不可更改。

      let blob = new Blob(array, options);
      
      • array:这是一个数组,可以包含多个数据部分,通常是 ArrayBuffer(二进制数据)、Array(字符串数据)等。

      • options:一个可选对象

        • type:指定 Blob 对象的 MIME 类型。MIME 类型是一种标准,用于表示文档、文件或字节流的性质和格式。例如,"text/plain" 表示纯文本文件,"image/jpeg" 表示 JPEG 格式的图片。如果没指定,默认是 "" 空字符串。

        • endings:指定在创建 Blob 对象时如何处理换行符。它有两个可选值:

          • transparent(默认值):不转换换行符,保留原始数据中的换行符。

          • native:将换行符转换为当前操作系统的本地换行符(例如,在 Windows 上是 \r\n,在 Unix/Linux 上是 \n)。

            示例:

            let text = "Hello, world!";
            let blob = new Blob([text], { type: "text/plain" });
            let url = URL.createObjectURL(blob);
            let a = document.createElement("a");
            a.href = url;
            a.download = "hello.txt";
            a.click();
            URL.revokeObjectURL(url)
            

            Blob 属性/方法

            属性/方法描述
            size获取 Blob 的大小(字节数)
            type获取 Blob 的类型(MIME类型)
            slice()Blob 分片。当你处理大文件时,可能需要将文件拆分成多个小块进行处理或上传。该方法可以让你提取文件的一部分并进行操作
            stream()返回一个 ReadableStream 对象,读取它将返回包含在 Blob 中的数据
            arrayBuffer()返回一个 ReadableStream 对象,读取它将返回包含在 Blob 中的数据

            slice():Blob 分片,其有三个参数:

            • start:设置切片的起点,即切片开始位置。默认值为 0,即从第一个字节开始

            • end:设置切片的结束点,会对该位置之前的数据进行切片。默认值为blob.size

            • contentType:设置新 blob 的 MIME 类型。如果省略 type,则默认为 blob 的原始值

              let text = "Hello, world!";
              let blob = new Blob([text], { type: "text/plain" });
              const subBlob = blob.slice(0, 5);
              let url = URL.createObjectURL(subBlob);
              let a = document.createElement("a");
              a.href = url;
              a.download = "hello.txt";
              a.click();
              URL.revokeObjectURL(url)
              // 此时下载的文件内容只有 Hello
              

              Blob 与 URL

              这里只介绍 URL.createObjectURL(blob); 方法。

              创建一个 Blob 对象后,我们可以使用 createObjectURL 方法将其转换为 URL 地址。该 URL 可以用于在浏览器中显示图片、下载文件等。

                
                
              
              
              import { onMounted, ref } from 'vue';
              const src = ref(null)
              onMounted(() => {
                const fileInput = document.getElementById("fileInput");
                fileInput.onchange = (e) => {
                  const file = e.target.files[0]
                  let url = URL.createObjectURL(file);
                  console.log(url)
                  src.value = url
                }
              })
              
              

              createObjectURL 注意事项:

              • 使用完 URL 后,需要手动释放,否则会导致内存泄漏 URL.revokeObjectURL(url);

              • IE 浏览器不支持 createObjectURL 方法

                下载文件上完整示例:

                api.downloadFile(params).then(res=>{
                	let blob = new Blob([res.result]);
                	if (window.navigator.msSaveOrOpenBlob) {
                		// 兼容 IE
                    	window.navigator.msSaveOrOpenBlob(blob, 'hello.txt');
                    } else {
                	    let url = window.URL.createObjectURL(blob);
                    	let a = document.createElement("a");
                		a.href = url;
                		a.download = "hello.txt";
                		document.body.appendChild(a)
                		a.click();
                		document.body.removeChild(a)
                		window.URL.revokeObjectURL(url)
                    }
                })
                

                Blob 与 Base64

                Base64 可以将二进制数据转换为为 ASCII 字符串。这样可以方便地在文本协议(如 HTTP、JSON)中传输二进制数据(实际传输的是字符串)。

                // 将字符串编码为 Base64:
                const text = 'Hello, world!';
                const base64String = btoa(text);
                console.log(base64String);  // 输出 Base64 编码的字符串
                // 将 Base64 字符串解码为原始字符串:
                const decodedText = atob(base64String);
                console.log(decodedText);  // 输出 'Hello, world!'
                // 通过 FileReader 将 Blob 转换为 Base64 字符串:
                const blob = new Blob(['Hello, world!'], { type: 'text/plain' });
                const reader = new FileReader();
                reader.onloadend = function() {
                  const base64String = reader.result.split(',')[1];  // 获取 Base64 部分
                  console.log(base64String);
                };
                reader.readAsDataURL(blob);
                
                区别BlobBase64
                存储方式Blob 用于存储原始的二进制数据Base64 是将二进制数据转为文本编码的字符串
                性能直接存储二进制数据,不会占用额外的空间,因此它处理大文件时性能更好会增加约 33% 的数据大小,因为每个 3 字节的二进制数据会被编码为 4 字节的 Base64 字符串
                应用场景适合处理文件上传/下载适合将二进制数据嵌入到 HTML 或 JavaScript 中(如图片在 HTML 中的嵌入)

                Blob 与 ArrayBuffer

                Blob 和 ArrayBuffer 都是用于处理二进制数据。ArrayBuffer 是底层的二进制数据存储容器,而 Blob 是一种更高级的类文件对象,它可以包含 ArrayBuffer。

                • ArrayBuffer 适合处理小块的二进制数据,因为它在内存中是连续存储的,读写速度较快。但如果数据量过大,可能会导致内存占用过高。

                • Blob 更适合处理大文件或流式数据,因为它不需要将整个数据加载到内存中。浏览器可以对 Blob 进行优化,例如分块读取和处理数据,从而减少内存占用。

                  ArrayBuffer 特点:

                  • 存储原始的二进制数据。

                  • 长度固定,创建后无法更改。

                  • 需要通过视图(如 Uint8Array、DataView 等)来读写数据。

                    在实际开发中,它们的使用场景常常是互补的。

                    ArrayBuffer 用于在内存中高效地处理和操作二进制数据,而 Blob 则更适合用于文件的存储、传输和展示等场景。

                    例如,在处理图片数据时,先将图片数据读取到 ArrayBuffer 中进行处理(如裁剪、压缩等),然后再将处理后的 ArrayBuffer 转换为 Blob 对象,通过 URL.createObjectURL() 生成临时 URL 展示图片或进行文件下载。

                    ArrayBuffer 转 Blob:当你有一个 ArrayBuffer 并且想把它当作一个文件来处理(比如下载、上传等)时,可以将其转换为 Blob 对象。

                    const buffer = new ArrayBuffer(16);
                    // 创建一个包含 ArrayBuffer 数据的 Blob 对象
                    const blob = new Blob([buffer], { type: 'application/octet-stream' });
                    

                    Blob 转 ArrayBuffer:当你需要对 Blob 中的数据进行底层操作时,可以将 Blob 转换为 ArrayBuffer。通常使用 FileReader 对象来完成这个转换。

                    const text = 'Hello, World!';
                    const blob = new Blob([text], { type: 'text/plain' });
                    const reader = new FileReader();
                    reader.readAsArrayBuffer(blob);
                    reader.onload = function() {
                        const buffer = reader.result;
                        console.log(buffer);
                    };
                    

                    Blob 与 File

                    File 是 Blob 的一个子类,扩展了 Blob 的功能。它不仅包含数据本身,还包含文件的元数据(如文件名、类型等)。

                    在 JavaScript 中,主要有两种方法来获取 File 对象:

                    • 元素上选择文件后返回的 FileList 数组,该数组的每个元素都是一个 File 对象

                        
                      
                      
                      import { onMounted } from 'vue';
                      onMounted(() => {
                        const fileInput = document.getElementById("fileInput");
                        fileInput.onchange = (e) => {
                          console.log(e.target.files);
                        }
                      })
                      
                      

                      前端系列之:Blob

                      • 文件拖放操作生成的 DataTransfer 对象

                          
                        import { onMounted } from 'vue'; onMounted(() => { const dropZone = document.getElementById("drop-zone"); dropZone.ondragover = (e) => { e.preventDefault(); } dropZone.ondrop = (e) => { e.preventDefault(); const files = e.dataTransfer.files; console.log(files) } }) #drop-zone { margin: auto; width: 100px; height: 100px; border: 1px solid #000; }

                        打印内容同上。

                        Blob 与 Streams

                        Blob 的局限性:Blob 对象是一次性读取整个数据,对于大文件来说,可能会占用大量的内存,导致性能问题。

                        Stream(数据流)是一种按顺序读取和写入数据的方式,通常用于处理大量数据而不将其一次性加载到内存中。Streams 可以通过分块逐步传输数据,使得程序能够在处理数据时节省内存资源。

                        使用场景:

                        • 文件读取与写入:流被广泛应用于文件的处理,尤其是当文件很大,不能一次性加载到内存时,流式处理可以分段读取并处理数据。

                        • 网络传输:流用于数据的实时传输,尤其是在处理音视频流、网络请求响应等场景下。

                        • 处理大数据:Stream 能够在读取大数据时逐块处理,而不是将整个数据加载到内存中,这样能节省内存并提高效率。

                          特点:

                          • 数据按块(chunk)逐步传输。

                          • 节省内存,特别适用于大文件的读取与写入。

                          • 异步操作,有助于处理 I/O 操作。

                            Blob 与 FileReader

                            FileReader 是一个用于异步读取 Blob 或 File 对象中内容的 API,并且可以将 Blob/File 读取为不同的格式(如文本、Base64 等)。

                            示例:

                              
                            
                            
                            import { onMounted } from 'vue';
                            onMounted(() => {
                              const fileInput = document.getElementById("fileInput");
                              fileInput.onchange = (e) => {
                                console.log(e.target.files);
                                const file = e.target.files[0]
                                if (file) {
                                  const reader = new FileReader();
                                  reader.onload = function (e) {
                                    console.log('文件内容:', e.target.result);
                                  };
                                  reader.readAsText(file);
                                }
                              }
                            })
                            // 这种写法也是一样的
                            onMounted(() => {
                              const fileInput = document.getElementById("fileInput");
                              const reader = new FileReader();
                              fileInput.onchange = (e) => {
                                reader.readAsText(e.target.files[0]);
                              }
                              reader.onload = (e) => {
                                console.log('文件内容:', e.target.result);
                              }
                            })
                            
                            

                            前端系列之:Blob

                            上传的文件就是最开始的 hello.txt。

                            FileReader 方法/事件

                            Web API > FileReader

                            方法描述
                            readAsArrayBuffer()开始读取指定的 Blob 中的内容,一旦完成,result 属性中将包含一个表示文件数据的 ArrayBuffer 对象。
                            readAsBinaryString()…result 属性中将包含一个表示文件中的原始二进制数据的字符串。
                            readAsDataURL()…result 属性中将包含一个表示文件数据的 data: URL
                            readAsText()…result 属性中将包含一个表示所读取的文件内容的字符串
                            事件描述
                            abort该事件在读取操作被中断时触发
                            error该事件在读取操作发生错误时触发
                            load该事件在读取操作完成时触发
                            loadend读取完成时触发,无论成功与否
                            loadstart读取开始时触发
                            progress读取数据时定期触发
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码