域名备案与网站不一致免费自建网站有哪些
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);
区别 | Blob | Base64 |
---|---|---|
存储方式 | 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 | 读取数据时定期触发 |