首页/文章/javascript

一图看懂ArrayBuffer、Blob、File、FileReader、MediaSource之间的关系

2024-11-22
17976 分钟
...

本文主要介绍了 ArrayBuffer、Blob、File、FileReader、MediaSource 之间的关系。ArrayBuffer 是固定长度的二进制数据缓冲区,通过 TypedArray 或 DataView 操作,常用于网络技术处理二进制数据。Blob 是类文件对象,File 是其子类。它们可通过特定方式创建、操作和应用。FileReader 用于异步读取文件内容。MediaSource 是媒体资源接口,与其他对象存在一定关联。

关联问题: 如何优化ArrayBuffer性能 FileReader使用注意事项 MediaSource的优势在哪

ArrayBuffer

ArrayBuffer 表示一个通用的、固定长度的原始二进制数据缓冲区。
ArrayBuffer 不能直接操作,而是通过类型化数组视图(TypedArray)(比如 Uint8ArrayFloat32Array 等)或者DataView 来操作。

应用:ArrayBuffer 经常与 Fetch API、WebSocket 等网络技术一起使用,用于处理二进制数据的接收和发送;可以用来处理文件、图像、音频、视频等二进制数据。

1. 创建实例

const buffer = new ArrayBuffer(16); 

2. 操作实例

1)类型化数组视图(TypedArray)
const view = new Uint8Array(buffer); 
view[0] = 255; 
2)DataView
const view = new DataView(buffer, 0);
view.setUint8(0, 255); 

3. 使用举例

刚好上一篇 前端实时播放摄像头RTSP流(H.265)解决方案 有用到

1)转换为字符串

我们不能直接将 ArrayBuffer 转换为字符串,但可以通过类型化数组视图等来实现:

private onWebSocketMessage = (buffer: ArrayBuffer) => { 
    const unit = new Uint8Array(buffer) 
    let unitCharCodeStr = '' 
    unit.forEach((u) => { 
        unitCharCodeStr += String.fromCharCode(u) 
    })
    console.log(unitCharCodeStr);
}
2)实时播放流媒体文件

SourceBuffer.appendBuffer:将来自 ArrayBufferTypedArray 或 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();
  
  mediaSource.addEventListener("sourceopen", sourceOpen);
  video.src = URL.createObjectURL(mediaSource);
} else {
  console.error("Unsupported MIME type or codec: ", mimeCodec);
}

function sourceOpen() {
  
  const mediaSource = this;
  const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
  fetchAB(assetURL, function (buf) {
    sourceBuffer.addEventListener("updateend", () => {
      mediaSource.endOfStream();
      video.play();
      
    });
    sourceBuffer.appendBuffer(buf);
  });
}

Blob、File

Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据操作。
File 是 Blob 的一个子类,表示文件系统中的文件,扩展了 name 、 lastModified 等属性,可以在 Blob 可以使用的任何上下文中使用。

应用:通常用于处理文件或二进制数据流,比如从网络下载文件或用户上传文件到服务器。

1. 创建实例

_new Blob(blobParts, options): _
blobParts:一个可迭代对象,比如 Array,包含 ArrayBufferTypedArrayDataViewBlob、字符串或者任意这些元素的混合,这些元素将会被放入 Blob中。
options:一个可以指定以下任意属性的对象,type(将会被存储到 blob 中的数据的 MIME 类型),endings(如果数据是文本,那么如何解释其中的换行符\n

_new File(blobParts, fileName, options): _
fileName:表示文件名或文件路径的字符串。
options:除typeendings外,还可指定lastModified(一个数字,表示 Unix 时间纪元与文件上次修改时间之间的毫秒数,默认值为 Date.now()返回值)


const blobParts = ['<q id="a"><span id="b">hey!</span></q>']; 
const blob = new Blob(blobParts, { type: "text/html" }); 


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);

const img = document.createElement('img');
img.src = url;
img.onload = () => {
    URL.revokeObjectURL(img.src);
};
document.body.appendChild(img);

URL.createObjectURL(object):
该静态方法对 object 对象创建一个临时的、唯一的 URL,它指向一个内存中的文件对象,而不是实际的文件系统中的文件。这个 URL 可以用于 imgvideoaudio 等元素的 src 属性。
其中 object 指用于创建 URL 的 FileBlob 或 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');
    
    
    const url = URL.createObjectURL(file);
    img.src = url; 
    img.onload = () => { 
        URL.revokeObjectURL(img.src); 
    }; 
    
    
    
    
    const reader = new FileReader();
    reader.onload = function(e) {
        img.src = e.target.result;
    };
    reader.readAsDataURL(file); 
    
    
    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

MediaSourceMedia Source Extensions API(媒体源扩展 API(MSE))中用于表示媒体资源 HTMLMediaElement 对象的接口。
使用 MSE,媒体串流能够通过 JavaScript 创建,并且能通过使用 <audio> 和 <video> 元素进行播放。

由于这块内容涉及面广,且本文主要介绍 ArrayBufferMediaSource 的关系,就不在此对 MSE 做展开介绍。 感兴趣的也可以看下上一篇 前端实时播放摄像头RTSP流(H.265)解决方案,有涉及到相关介绍和应用。

总结

总体关系可大致为下面两条线:

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
javascript2026-02-24
navigator.sendBeacon全指南
在前端开发中,埋点系统是必不可少的一环。我们经常需要在用户 关闭页面 、 刷新 或 跳转路由 时,向服务器发送最后一条统计数据(比如用户停留时长、页面跳出率)。 但这看似简单的需求,在实现时却危机四伏:请求发不出去?页面跳转卡顿?今天我们就来聊聊这个问题的终极解决方案 —— 。 一、 痛点与传统方案的挣扎 场景还原 当用户点击关闭按钮时,浏览器会触发生命周期事件( 或 )。如果我们直接使用普通的异步 AJAX ( 或 ) 发送请求,浏览...
学习
javascript2025-11-02
理解浏览器事件系统,从用户点击到事件对象的完整旅程
深入理解浏览器事件系统:从用户点击到事件对象的完整旅程 “当我点击页面按钮时,背后发生了什么?为什么回调函数能收到一个包含丰富信息的event对象?今天,让我们一起揭开浏览器事件系统的神秘面纱。” 一个令人困惑的现象 作为前端开发者,我们每天都在写这样的代码: 这段代码如此熟悉,以至于我们很少停下来思考:​ ​这个 对象到底从哪里来?它为什么能知道点击的精确坐标?为什么能识别是哪个元素被点击了?​ ​ 更神奇的是,当我们手动创建事件时:...
学习
javascript2025-10-01
实现大文件上传全流程详解
在日常开发中,大文件上传是个绕不开的坎——动辄几百 MB 甚至 GB 级的文件,直接上传不仅容易超时,还会让用户体验大打折扣。最近我用 Vue+Express 实现了一套完整的大文件上传方案,支持分片上传、断点续传、秒传和手动中。 一、先看效果:我们要实现什么? 先上核心功能清单,确保大家明确目标,知道我们要解决哪些实际问题: 大文件分片上传 :将文件切成固定大小的小片段分批上传,避免单次请求超时 秒传 :服务器已存在完整文件时,直接返...
学习
javascript2025-09-18
JavaScript 的多线程能力:Worker
如果你写过一些计算量稍大的 JavaScript 代码,比如图像处理、大量数据排序或者复杂的算法,你几乎肯定遇到过浏览器“卡死”的现象。点击页面没反应,动画也停了,就像整个世界都静止了。 这就是主线程被阻塞的典型后果。因为主线程既要负责执行 JavaScript,又要负责渲染页面、响应用户操作,一旦它被繁重的计算任务占满,就无暇顾及其他,用户体验便直线下降。 这个问题的根源,正是“主线程是单线程的”。那么,如何解决呢? 答案很简单:把这...
学习面试
javascript2025-09-15
一张 8K 海报差点把首屏拖垮
你给后台管理系统加了一个「企业风采」模块,运营同学一口气上传了 200 张 8K 宣传海报。首屏直接飙到 8.3 s,LCP 红得发紫。 老板一句「能不能像朋友圈那样滑到哪看到哪?」——于是你把懒加载重新翻出来折腾了一轮。 解决方案:三条技术路线,你全踩了一遍 1\. 最偷懒:原生 一行代码就能跑,浏览器帮你搞定。 🔍 关键决策点 2020 年后现代浏览器全覆盖,IE 全军覆没。 必须写死 ,否则 CLS 会抖成 PPT。 适用场景...
学习
javascript2025-09-10
🚀 Web Worker让你的应用丝滑
🌟 引言 在日常的前端开发中,你是否遇到过这样的困扰: 大数据处理时页面卡死 :处理几万条数据时,页面直接卡成PPT,用户点击毫无反应 复杂计算阻塞UI :图片处理、数据分析等计算密集型任务让整个应用假死 文件上传/下载卡顿 :大文件操作时,其他功能完全无法使用 实时数据处理性能差 :WebSocket接收大量数据时,页面渲染严重滞后 今天分享6个Web Worker的核心技巧,让你的应用告别卡顿,用户体验丝滑如德芙! 💡 核心技巧...
学习

评论

请登录后发表评论

去登录
加载评论中...

目录