ArrayBuffer
ArrayBuffer
表示一个通用的、固定长度的原始二进制数据缓冲区。
ArrayBuffer
不能直接操作,而是通过类型化数组视图(TypedArray)(比如 Uint8Array
、Float32Array
等)或者DataView 来操作。
应用:
ArrayBuffer
经常与 Fetch API、WebSocket 等网络技术一起使用,用于处理二进制数据的接收和发送;可以用来处理文件、图像、音频、视频等二进制数据。
1. 创建实例
const buffer = new ArrayBuffer(16); // 创建一个16字节的ArrayBuffer
2. 操作实例
1)类型化数组视图(TypedArray)
const view = new Uint8Array(buffer); // 0 到 255 一个 8 位无符号整型数组
view[0] = 255; // 设置第一个字节的值为255
2)DataView
const view = new DataView(buffer, 0);
view.setUint8(0, 255); // 在视图开始的指定字节偏移处存储一个无符号 8 位整数,设置第一个字节的值为255
3. 使用举例
刚好上一篇 前端实时播放摄像头RTSP流(H.265)解决方案 有用到
1)转换为字符串
我们不能直接将 ArrayBuffer
转换为字符串,但可以通过类型化数组视图
等来实现:
private onWebSocketMessage = (buffer: ArrayBuffer) => { // ws 推过来的视频流
const unit = new Uint8Array(buffer)
let unitCharCodeStr = ''
unit.forEach((u) => {
unitCharCodeStr += String.fromCharCode(u)
})
console.log(unitCharCodeStr);
}
2)实时播放流媒体文件
SourceBuffer.appendBuffer:将来自 ArrayBuffer
、TypedArray
或 DataView
对象的媒体片段数据附加到 SourceBuffer
。
官方示例:
const assetURL = "frag_bunny.mp4";
const mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
if ("MediaSource" in window && MediaSource.isTypeSupported(mimeCodec)) {
const mediaSource = new MediaSource();
//console.log(mediaSource.readyState); // closed
mediaSource.addEventListener("sourceopen", sourceOpen);
video.src = URL.createObjectURL(mediaSource);
} else {
console.error("Unsupported MIME type or codec: ", mimeCodec);
}
function sourceOpen() {
//console.log(this.readyState); // open
const mediaSource = this;
const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
fetchAB(assetURL, function (buf) {
sourceBuffer.addEventListener("updateend", () => {
mediaSource.endOfStream();
video.play();
//console.log(mediaSource.readyState); // ended
});
sourceBuffer.appendBuffer(buf);
});
}
Blob、File
Blob
对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据操作。
File
是 Blob 的一个子类,表示文件系统中的文件,扩展了 name
、 lastModified
等属性,可以在 Blob 可以使用的任何上下文中使用。
应用:通常用于处理文件或二进制数据流,比如从网络下载文件或用户上传文件到服务器。
1. 创建实例
new Blob(blobParts, options):
blobParts:一个可迭代对象,比如Array
,包含ArrayBuffer
、TypedArray
、DataView
、Blob
、字符串或者任意这些元素的混合,这些元素将会被放入Blob
中。
options:一个可以指定以下任意属性的对象,type
(将会被存储到 blob 中的数据的 MIME 类型),endings
(如果数据是文本,那么如何解释其中的换行符\n
)
new File(blobParts, fileName, options):
fileName:表示文件名或文件路径的字符串。
options:除type
、endings
外,还可指定lastModified
(一个数字,表示 Unix 时间纪元与文件上次修改时间之间的毫秒数,默认值为Date.now()
返回值)
// Blob
const blobParts = ['<q id="a"><span id="b">hey!</span></q>']; // 一个包含单个字符串的数组
const blob = new Blob(blobParts, { type: "text/html" }); // 得到 blob
// File
const file = new File(["foo"], "foo.txt", {
type: "text/plain",
});
在实际应用中,
File
对象通常从用户使用<input>
元素选择文件返回的FileList
对象中检索,或者从拖放操作返回的DataTransfer
对象中检索
2. 操作实例
File
可以在 Blob
可以使用的任何上下文中使用
1)实例方法:可读取或切片数据
2)通过FileReader
读取数据
const reader = new FileReader();
reader.onload = function(event) {
console.log(event.target.result); // 读取到的数据
};
reader.readAsText(blob);
FileReader
相关API介绍见后文
3)利用URL.createObjectURL(blob)
将 Blob
转换为 URL
const url = URL.createObjectURL(blob);
// 将 URL 用于图像
const img = document.createElement('img');
img.src = url;
img.onload = () => {
URL.revokeObjectURL(img.src);
};
document.body.appendChild(img);
URL.createObjectURL(object):
该静态方法对object
对象创建一个临时的、唯一的 URL,它指向一个内存中的文件对象,而不是实际的文件系统中的文件。这个 URL 可以用于img
、video
、audio
等元素的src
属性。
其中object
指用于创建 URL 的File
、Blob
或MediaSource
对象。
3. 使用举例
<input type="file" id="fileInput">
1)本地图片预览(File
)
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', (event) => {
const files = event.target.files;
if (files.length > 0) {
const file = files[0];
const img = document.createElement('img');
// 方案1: 使用 URL.createObjectURL()
// start
const url = URL.createObjectURL(file);
img.src = url;
img.onload = () => {
URL.revokeObjectURL(img.src);
};
// end
// 方案2: 使用 FileReader()
// start
const reader = new FileReader();
reader.onload = function(e) {
img.src = e.target.result;
};
reader.readAsDataURL(file); // base64
// end
document.body.appendChild(img);
}
});
2)本地文件上传(File
)
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', (event) => {
const files = event.target.files;
if (files.length > 0) {
const file = files[0];
const formData = new FormData();
formData.append('file', file);
fetch('xxxxx', {
method: 'POST',
body: formData
})
.then(response => response.json())
}
});
3)文件下载(Blob
)
/* 从服务器下载 */
fetch('xxxxxxx')
.then(response => response.blob())
.then(blob => {
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = 'filename.txt';
document.body.appendChild(a);
a.click();
a.remove();
URL.revokeObjectURL(url);
})
/* 前端生成文件内容并下载 */
const testJson = {
config: {"aa": 11, "bb": 22},
inputDatas: [{"int1":23}, {"int2":34}]
};
const jsonBlob = new Blob([JSON.stringify(testJson, null, 2)], {type: 'application/json'});
const url = window.URL.createObjectURL(jsonBlob);
let a = window.document.createElement('a');
a.href = url;
a.download = 'test.json';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
FileReader
FileReader
允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File
或 Blob
对象指定要读取的文件或数据。
文件对象可以从 <input>
选择文件后的 FileList
中获取,或者从拖放的 DataTransfer
中获取。
应用:提供一种方便的方式在客户端处理文件,无需服务器的介入。使得可以实现如图片预览、文件内容编辑等客户端功能。
1. 创建实例
const reader = new FileReader();
2. 操作实例
当读取操作完成时,readyState 属性变为 DONE,并触发 loadend 事件
3. 使用举例
使用 FileReader
读取文本文件
document.getElementById('fileInput').addEventListener('change', function(event) {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
console.log(e.target.result); // 打印文件内容
};
reader.onerror = function(e) {
console.error('读取文件时出错:', e.target.error);
};
reader.readAsText(file); // 以文本形式读取文件
}
});
其他API使用,例如 readAsDataURL
已在上文提及,就不再赘述
MediaSource
MediaSource
是 Media Source Extensions API(媒体源扩展 API(MSE))中用于表示媒体资源 HTMLMediaElement
对象的接口。
使用 MSE,媒体串流能够通过 JavaScript 创建,并且能通过使用 <audio>
和 <video>
元素进行播放。
由于这块内容涉及面广,且本文主要介绍 ArrayBuffer
和 MediaSource
的关系,就不在此对 MSE
做展开介绍。
感兴趣的也可以看下上一篇 前端实时播放摄像头RTSP流(H.265)解决方案,有涉及到相关介绍和应用。
总结
总体关系可大致为下面两条线: