当前位置: 首页 > news >正文

前端系列之:Blob

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 可以用于在浏览器中显示图片、下载文件等。

<template><input type="file" id="fileInput" multiple="multiple"><img :src="src">
</template><script setup>
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}
})
</script>

createObjectURL 注意事项:

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

  • IE 浏览器不支持 createObjectURL 方法

下载文件上完整示例:

api.downloadFile(params).then(res=>{let blob = new Blob([res.result]);if (window.navigator.msSaveOrOpenBlob) {// 兼容 IEwindow.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 对象

    <template><input type="file" id="fileInput" multiple="multiple">
    </template><script setup>
    import { onMounted } from 'vue';onMounted(() => {const fileInput = document.getElementById("fileInput");fileInput.onchange = (e) => {console.log(e.target.files);}
    })
    </script>
    

在这里插入图片描述

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

    <template><div id="drop-zone"></div>
    </template><script setup>
    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)}
    })
    </script><style scoped>
    #drop-zone {margin: auto;width: 100px;height: 100px;border: 1px solid #000;
    }
    </style>
    

    打印内容同上。

Blob 与 Streams

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

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

使用场景:

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

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

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

特点:

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

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

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

Blob 与 FileReader

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

示例:

<template><input type="file" id="fileInput" multiple="multiple">
</template><script setup>
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);}
})
</script>

在这里插入图片描述

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

FileReader 方法/事件

Web API > FileReader

方法描述
readAsArrayBuffer()开始读取指定的 Blob 中的内容,一旦完成,result 属性中将包含一个表示文件数据的 ArrayBuffer 对象。
readAsBinaryString()…result 属性中将包含一个表示文件中的原始二进制数据的字符串。
readAsDataURL()…result 属性中将包含一个表示文件数据的 data: URL
readAsText()…result 属性中将包含一个表示所读取的文件内容的字符串
事件描述
abort该事件在读取操作被中断时触发
error该事件在读取操作发生错误时触发
load该事件在读取操作完成时触发
loadend读取完成时触发,无论成功与否
loadstart读取开始时触发
progress读取数据时定期触发

相关文章:

前端系列之:Blob

Blob 与二进制 什么是二进制&#xff1f; 二进制是计算机数据的基本表示形式&#xff0c;只使用 0 和 1 两个数字来表示数值。任何类型的数据&#xff08;无论是文本、图片、音频文件等&#xff09;都可以通过二进制表示。 什么是 Blob&#xff1f; 全称 Binary Large Object&a…...

【项目管理】基于 C 语言的 QQ 聊天室实现(TCP + 多线程 + SQLite3)

基于 C 语言的 QQ 聊天室(TCP + 多线程 + SQLite3) 项目功能基础功能: 登录、注册、添加好友、私聊、创建群聊、群聊扩展功能: 删除好友、注销账号、好友在线状态、群管理(拉人/踢人)、VIP 特权、邮件通知等 功能介绍:模拟QQ聊天客户端:登录界面:1、登录2、注册 //将用…...

Apache Flink:实时数据流处理的终极武器

Apache Flink&#xff1a;实时数据流处理的终极武器 在当今这个数据驱动的世界&#xff0c;实时数据流处理已经成为各行各业的核心需求。从金融风控到电商推荐&#xff0c;从物联网监控到网络安全&#xff0c;毫秒级的响应能力决定了一家公司在市场中的竞争力。而在众多流式计…...

点云处理入门--PointNetPointNet++论文与代码详解

基础知识 点云数据&#xff1a; 点云是一种通过三维扫描设备或计算机图形学技术获取的三维空间数据&#xff0c;通常由一系列点组成&#xff0c;每个点包含其在三维空间中的坐标&#xff08;如 x,y,z&#xff09;&#xff0c;有时还可能包含颜色、强度等附加信息。 介绍几种常…...

通过Nginx负载均衡+Keepalived实现业务高可用

通过Nginx负载均衡和Keepalived可以实现业务的高可用&#xff0c;以下是详细的实现步骤&#xff1a; 环境准备 假设我们有3台服务器&#xff0c;IP地址分别为&#xff1a; 服务器1&#xff08;Nginx Keepalived 主节点&#xff09;&#xff1a;192.168.1.100服务器2&#x…...

Spark技术系列(三):Spark算子全解析——从基础使用到高阶优化

Spark技术系列(三):Spark算子全解析——从基础使用到高阶优化 1. 算子核心概念与分类体系 1.1 算子本质解析 延迟执行机制:转换算子构建DAG,行动算子触发Job执行任务并行度:由RDD分区数决定(可通过spark.default.parallelism全局配置)执行位置优化:基于数据本地性的…...

ES6模块化详解:导入与导出方式

在现代 JavaScript 开发中&#xff0c;模块化是代码管理和组织的重要工具。ES6&#xff08;ECMAScript 2015&#xff09;引入了模块化的概念&#xff0c;通过 import 和 export 来组织代码&#xff0c;使得模块的管理变得更加清晰和简洁。本文将详细介绍 ES6 中的各种模块导入导…...

每日学习Java之一万个为什么?[MySQL面试篇]

分析SQL语句执行流程中遇到的问题 前言1 MySQL是怎么在一台服务器上启动的2 MySQL主库和从库是同时启动保持Alive的吗&#xff1f;3 如果不是主从怎么在启动的时候保证数据一致性4 ACID原则在MySQL上的体现5 数据在MySQL是通过什么DTO实现的6 客户端怎么与MySQL Server建立连接…...

常用空间数据结构对比

空间数据结构是用来组织和查询多维空间数据的算法结构。它们在地理信息系统 (GIS)、计算机图形学、机器人导航、机器学习等领域非常重要。以下是几种常见空间数据结构的对比&#xff1a; 1. 四叉树&#xff08;Quadtree&#xff09; 适用场景&#xff1a;二维空间数据&#x…...

AnythingLLM+LM Studio本地知识库构建

前置操作&#xff1a; 已经安装以下软件&#xff0c;并配置后&#xff1a; DeepSeek-R1-Distill-Llama-8B-Q4_K_M.ggufLM-Studio-0.3.10-6-x64 软件准备&#xff1a; 下载AnythingLLM&#xff1a;AnythingLLM | The all-in-one AI application for everyone 点击"Dow…...

使用 Java 更新 Word 文档中的图表数据-超详细

使用 Java 更新 Word 文档中的图表数据 在日常的工作中&#xff0c;尤其是在数据分析和报告自动化的场景中&#xff0c;可能会遇到需要定期更新 Word 文档中的图表数据的需求。比如&#xff0c;生成数据报告时&#xff0c;我们需要在图表中更新一些动态的数据值。今天&#xf…...

Qt常用控件之下拉框QComboBox

下拉框QComboBox QComboBox 是一个下拉框控件。 1. QComboBox属性 属性说明currentText当前选中的文本。currentIndex当前选中的条目下标&#xff08;从 0 开始&#xff0c;如果没有条目被选中则该值为 -1&#xff09;。editable是否允许被修改。为 true 时&#xff0c;QCom…...

Qt 中集成mqtt协议

一&#xff0c;引入qmqtt 库 我是将整个头文件/源文件都添加到了工程中进行编译&#xff0c;这样 跨平台时 方便&#xff0c;直接编译就行了。 原始仓库路径&#xff1a;https://github.com/emqx/qmqtt/tree/master 二&#xff0c;使用 声明一个单例类&#xff0c;将订阅到…...

2024年第十五届蓝桥杯大赛软件赛省赛Python大学A组真题解析

文章目录 试题A: 拼正方形(本题总分:5 分)解析答案试题B: 召唤数学精灵(本题总分:5 分)解析答案试题C: 数字诗意解析答案试题A: 拼正方形(本题总分:5 分) 【问题描述】 小蓝正在玩拼图游戏,他有7385137888721 个2 2 的方块和10470245 个1 1 的方块,他需要从中挑出一些…...

AI大模型-提示工程学习笔记19-自我反思

目录 1. 自我反思的核心思想 (1) LLM 的局限性 (2) Reflexion 的解决方案 2. Reflexion 的工作流程 (1) 任务输入 (2) 初始生成 (3) 反思 (Reflection) (4) 调整与改进 (5) 迭代 (6) 结果输出 3. Reflexion 的关键组件 (1) 大语言模型 (LLM) (2) 反思者 (Reflector…...

GaussDB 学习实战指南:从部署到高并发优化的全流程解析

引言 GaussDB 作为华为推出的高性能分布式数据库,凭借其 分布式架构、高可用性、云原生支持 等特性,成为企业级应用的核心选择。本文将以 实战操作为核心,覆盖 集群部署、数据分片、性能调优、容灾备份、云上迁移 五大场景,通过真实案例与代码示例,助你快速掌握 GaussDB …...

vue3 Props的使用

Props是什么&#xff1f; 官方地址&#xff1a;Props | Vue.js 在 Vue 中&#xff0c;props 是父组件向子组件传递数据的一种机制。 props 是子组件中定义的自定义属性&#xff0c;父组件通过这些属性向子组件传递数据。 它们是单向数据流的一部分&#xff0c;意味着数据只能…...

Ecode前后端传值

说明 在泛微 E9 系统开发过程中&#xff0c;使用 Ecode 调用后端接口并进行传值是极为常见且关键的操作。在上一篇文章中&#xff0c;我们探讨了 Ecode 调用后端代码的相关内容&#xff0c;本文将深入剖析在 Ecode 中如何向后端传值&#xff0c;以及后端又该如何处理接收这些值…...

【Linux】进程状态(二)

目录 前言&#xff1a; 一、进程状态&#xff1a; 1.运行状态(时间片) 2.阻塞状态 3.阻塞挂起状态 二、Linux进程状态&#xff1a; 1.运行状态(R)和阻塞状态(S) 2.深度睡眠状态(D) 3.停止状态(T) 3.1使进程在后台运行 4.追踪暂停状态(t) 5.死亡状态(X)和僵尸状态…...

domain 网络安全 网络安全域

&#x1f345; 点击文末小卡片 &#xff0c;免费获取网络安全全套资料&#xff0c;资料在手&#xff0c;涨薪更快 文章目录 1、域的概述 1.1、工作组与域1.2、域的特点1.3、域的组成1.4、域的部署概述1.5、活动目录1.6、组策略GPO 2、域的部署实验 2.1、建立局域网&#xf…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...