前言
说起Blob
对于一部分人来说会很陌生,因为没有接触过,包括我之前也没有接触过,后来一个功能的实现才有机会接触Blob
,现在来学习一下Blob
的使用场景。后面有代码仓库地址
正文
什么是Blob
Blob
对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream
来用于数据操作。
创建一个Blob对象
ini
var aBlob = new Blob( array, options );
-
array 是一个由
ArrayBuffer
,ArrayBufferView
,Blob
,DOMString
等对象构成的Array
,或者其他类似对象的混合体,它将会被放进Blob
。DOMStrings 会被编码为 UTF-8。 -
options 是一个可选的
BlobPropertyBag
字典,它可能会指定如下两个属性:type
,默认值为""
,它代表了将会被放入到 blob 中的数组内容的 MIME 类型。常见的MIME类型text/plain
:纯文本文件text/html
:HTML 文档text/css
:CSS 样式表application/javascript
:JavaScript 脚本application/json
:JSON 数据image/jpeg
:JPEG 图像image/png
:PNG 图像audio/mpeg
:MP3 音频video/mp4
:MP4 视频
endings
,默认值为"transparent"
,用于指定包含行结束符\n
的字符串如何被写入。- "transparent":表示不对文本数据进行行尾符号的转换。这是默认值。
- "native":表示将文本数据的行尾符号转换为当前平台的本地行尾符号。
Blob属性
- size(只读):表示
Blob
对象中所包含数据的大小(以字节为单位)。 - type(只读):一个字符串,表明该
Blob
对象所包含数据的 MIME 类型。如果类型未知,则该值为空字符串。
Blob方法
-
返回一个 promise,其会兑现一个包含
Blob
所有内容的二进制格式的ArrayBuffer
。 -
返回一个新的
Blob
对象,包含了源Blob
对象中指定范围内的数据。 -
返回一个能读取
Blob
内容的ReadableStream
。 -
返回一个 promise,其会兑现一个包含
Blob
所有内容的 UTF-8 格式的字符串。
Blob实现上传图片浏览
代码很简单很容易看懂,介绍一下URL.createObjectURL()
和URL.revokeObjectURL()
。
URL.createObjectURL()
静态方法会创建一个 DOMString
,其中包含一个表示参数中给出的对象的 URL。这个 URL 的生命周期和创建它的窗口中的 document
绑定。这个新的 URL 对象表示指定的 File
对象或 Blob
对象。
在每次调用 createObjectURL()
方法时,都会创建一个新的 URL 对象,即使你已经用相同的对象作为参数创建过。当不再需要这些 URL 对象时,每个对象必须通过调用 URL.revokeObjectURL()
方法来释放。
base64
形式和Blob URL
形式的src
中数据差别很大,二者各有各的优势
- Blob URL 可以更好地处理大型文件,因为Blob URL不会将整个文件读入内存中,
FileReader
会将整个文件读入内存中。 - Blob URL 可以更好地保护用户的隐私,因为它们不会将文件的内容暴露给第三方,
base64
编码可以在任何应用程序中使用。 - Blob URL生命周期和创建它的窗口中的
document
绑定,base64
可以用于存储和传输文件。
base64形式
Blob URL形式
tsx
import { useState, useEffect, useRef, useMemo, useCallback } from 'react'
import { IconSty, UploadImgFrameSty } from './style';
import { PlusOutlined } from '@ant-design/icons';
import { Button } from 'antd';
export default function BlobUse() {
const [imgUrl, setImgUrl] = useState('')
const [isShow, setIsShow] = useState(false)
const inputDom = useRef(null)
const selectFile = useCallback((e: any) => {
//Blob URL
if (imgUrl) {
window.URL.revokeObjectURL(imgUrl)
}
const url = window.URL.createObjectURL(e.target.files[0]);
setImgUrl(url)
setIsShow(true)
//base64
// const file = e.target.files[0];
// const reader = new FileReader();
// reader.readAsDataURL(file);
// reader.onload = () => {
// setImgUrl(reader.result as string);
// setIsShow(true);
// };
}, [imgUrl])
useEffect(() => {
return () => {
imgUrl && window.URL.revokeObjectURL(imgUrl)
}
}, [])
return (
<>
<h3>Blob 实现本地图片预览</h3>
<UploadImgFrameSty>
{
!isShow && <IconSty>
<PlusOutlined />
</IconSty>
}
<input ref={inputDom} type="file" onChange={selectFile} accept="image/*" />
{isShow && <img src={imgUrl} />}
</UploadImgFrameSty>
</>
)
}
Blob实现JSON文件下载
这里还是利用URL.createObjectURL()
和URL.revokeObjectURL()
,再配合JSON.stringify
用来调整文件内容格式。
JSON.stringify(value[, replacer [, space]])
-
value
将要序列化成 一个 JSON 字符串的值。
-
replacer
可选 ,如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;如果该参数为 null 或者未提供,则对象所有的属性都会被序列化。
-
space
可选 ,指定缩进用的空白字符串,用于美化输出(pretty-print);如果参数是个数字,它代表有多少的空格;上限为 10。该值若小于 1,则意味着没有空格;如果该参数为字符串(当字符串长度超过 10 个字母,取其前 10 个字母),该字符串将被作为空格;如果该参数没有提供(或者为 null),将没有空格。
tsx
import { useState, useEffect, useRef, useMemo, useCallback } from 'react'
import { IconSty, UploadImgFrameSty } from './style';
import { PlusOutlined } from '@ant-design/icons';
import { Button } from 'antd';
export default function BlobUse() {
const clickDownload = useCallback(() => {
const data = {
name: '张三',
age: 18,
second: "我不会出现在下载的数据中",
};
downloadJson(data, "json.json");
}, [])
/** 下载JSON文件*/
const downloadJson = useCallback((data: any, filename: string) => {
if (!data) {
alert("保存的数据为空");
return;
}
if (!filename) {
filename = "json.json";
}
if (typeof data === "object") {
data = JSON.stringify(data, null, 4);
}
let blob = new Blob([data], { type: "text/json" });
//创建一个a标签进行下载
let a = document.createElement("a");
a.download = filename;
a.href = window.URL.createObjectURL(blob);
a.click();
URL.revokeObjectURL(a.href);
}, [])
return (
<>
<h3>下载JSON文件</h3>
<Button type="primary" onClick={clickDownload}>下载JSON文件</Button>
</>
)
}
Blob实现文件下载
后端以流的形式返回文件数据,我们通过将请求头responseType
设置为blob
,表示我们期望服务器响应的数据以二进制形式返回,并封装在一个Blob对象中。然后通过URL.createObjectURL
配合动态生成a
标签来下载文件。
具体的实现看这个:
从前后端代码看文件下载方式 - 掘金 (juejin.cn)
Blob文件切片上传
Blob 表示的不一定是 JavaScript 原生格式的数据。File
接口基于 Blob
,继承了 blob
的功能并将其扩展以支持用户系统上的文件。
文件切片使用的slice
方法,其实就是Blob
身上的slice
方法,具体的实现可以去看看之前写的文章
前端切片上传文件(可暂停),以链接形式返回 - 掘金 (juejin.cn)