前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >万字长文带你学习【前端开发中的二进制数据】| 技术创作特训营第五期

万字长文带你学习【前端开发中的二进制数据】| 技术创作特训营第五期

原创
作者头像
程序员库里
发布2024-01-24 12:54:37
2840
发布2024-01-24 12:54:37
举报
文章被收录于专栏:全栈学习全栈学习

介绍

在现代前端开发中,处理二进制数据变得越来越重要。从图像、音频到文件上传,这些数据类型常常以二进制形式存在。这个分享将带你深入探索 ArrayBuffer、Blob、File 以及流(Stream)等概念,探讨它们如何在前端开发中发挥作用,解锁了解和利用二进制数据的强大能力。

为什么二进制数据重要?

传统上,前端开发主要关注文本和结构化数据,但随着应用程序的复杂性增加,处理图像、音频和大型文件等二进制数据变得至关重要。这种数据的处理需要特定的工具和技术,而 ArrayBuffer、Blob、File 以及流(Stream)就提供了这样的能力。

概述概念
  • ArrayBuffer

ArrayBuffer 是 JavaScript 中用于表示一段固定长度的原始二进制数据的对象。它提供了一个固定大小的缓冲区,但不能直接读取或写入数据。相反,你需要使用 TypedArrays 或 DataView 对其进行操作和访问。

  • Blob 和 File

Blob 和 File 是用于表示二进制数据的对象。Blob(Binary Large Object)用于存储不可变的原始数据,而 File 对象是 Blob 的一种特殊形式,它包含了与文件相关的额外元数据,比如文件名、文件大小等信息。Blob 和 File 通常用于处理文件、图像、音频等二进制数据。

  • 流(Stream)

流是一种处理大量数据或实时数据的方式。在前端开发中,流提供了一种以逐段方式读取和处理数据的机制,避免一次性加载整个数据集到内存中。流在处理网络数据、大文件或实时数据时非常有用,它允许逐步处理数据,减少内存占用并提高性能。

  • TypedArrays

TypedArrays 是 JavaScript 中一系列特定类型的数组,比如 Uint8Array、Float32Array 等。它们基于 ArrayBuffer,允许以不同的数据类型(如整数或浮点数)操作二进制数据,提供了更高效的二进制数据处理方式。

Blob 和 File 的关系:

  1. Blob 是基础
    1. Blob 是一种表示不可变的原始二进制数据的对象,它可以包含任意类型的数据。File 对象继承自 Blob,因此 File 也具有 Blob 的所有特性。

2. File 是 Blob 的拓展

  • FileBlob 的拓展,它包含了一些额外的元数据,如文件名、最后修改时间、文件大小等。这使得 File 更适合用于表示用户通过文件输入字段选择的文件。

3. 创建方式

你可以使用 Blob 构造函数创建一个通用的 Blob 对象,而使用 File 构造函数创建一个表示文件的 File 对象。但需要注意,File 构造函数除了接受数据和文件名外,还可以接受一些可选的参数,如最后修改时间等。

Blob创建方式

语法
代码语言:javascript
复制
var a Blob = new Blob( array, options );
参数
  • array 是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的 Array ,或者其他类似对象的混合体,它将会被放进 Blob。DOMStrings 会被编码为 UTF-8。
  • options 是一个可选的BlobPropertyBag字典,它可能会指定如下两个属性:
    • type,默认值为 "",它代表了将会被放入到 blob 中的数组内容的 MIME 类型。
    • endings,默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。它是以下两个值中的一个:"native",代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 "transparent",代表会保持 blob 中保存的结束符不变 非标准
代码语言:javascript
复制
// 创建一个通用的 Blob 对象
const blob = new Blob(['Hello, Blob!'], { type: 'text/plain' });

// 创建一个表示文件的 File 对象
const file = new File(['Hello, File!'], 'example.txt', { type: 'text/plain', lastModified: Date.now() });

File构造方式

File() 构造器创建新的 File 对象实例。

语法
代码语言:javascript
复制
new File(bits, name)
new File(bits, name, options)
参数
  • bits:可迭代对象,如数组,包含 ArrayBuffers、TypedArrays、DataViews、Blobs、字符串等元素的集合,将被放入 File 中。需要注意的是,这里的字符串使用 UTF-8 编码,与通常的 JavaScript UTF-16 字符串不同。
  • name:字符串,表示文件名或文件路径。
  • options(可选):一个包含文件的可选属性的对象。可用的选项如下:
    • type:字符串,表示将要放入文件中的内容的 MIME 类型。默认值为 ""。
    • lastModified:数字,表示文件最后修改时间与 Unix 时间纪元之间的毫秒数。默认值为 Date.now()。
示例
代码语言:javascript
复制
var file = new File(["foo"], "foo.txt", {type: "text/plain",});

4. 用途

  • Blob 主要用于表示任意类型的二进制数据,而 File 更适合用于表示文件,特别是在涉及到用户上传文件时。
代码语言:javascript
复制
// 使用 Blob 创建 URL 并显示在页面上
const blobUrl = URL.createObjectURL(blob);

// 使用 File 创建 URL 并显示在页面上
const fileUrl = URL.createObjectURL(file);

总体来说,File 可以看作是 Blob 的子集,它在 Blob 的基础上添加了文件相关的元数据,使得它更适合处理文件的场景。在很多情况下,你可以使用 Blob 来表示一般的二进制数据,而在处理用户上传的文件时,使用 File 会更为合适。

ArrayBuffer和DataView以及TypedArrays之间的关系

当涉及到JavaScript中的二进制数据处理时,ArrayBufferDataView 和 Typed Arrays 是密切相关的。

他们的关系如下图所示,TypedArray和DataView都是Arraybuffer的视图,可以通过这两个数据类型去操作原始的二进制数据。

  • ArrayBuffer:
    • ArrayBuffer 是一种通用的、固定长度的二进制数据缓冲区。它表示一段连续的、通常是固定大小的内存区域,但是不能直接进行读写操作。它是一种容器,用于存储二进制数据,但没有提供直接的方法来操作这些数据。
  • Typed Arrays:
    • Typed Arrays 是一组特定类型的数组,它们直接基于 ArrayBuffer。Typed Arrays 提供了对 ArrayBuffer 中存储的二进制数据的结构化访问和操作能力。这些类型化数组包括 Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array 等等,每个都对应着不同的二进制数据格式。
  • DataView:
    • DataView 是一个允许你以不同的数据格式(例如整数、浮点数等)从 ArrayBuffer 中读取和写入数据的机制。它提供了一种灵活的方式来解释 ArrayBuffer 中的数据,因此你可以根据需要以不同的格式读取或写入数据。

关系可以总结如下:

  • ArrayBuffer 提供了存储二进制数据的固定大小缓冲区。
  • Typed Arrays 使用 ArrayBuffer 的内存,提供了对二进制数据的结构化访问和操作。
  • DataView 允许以不同的数据格式查看和修改 ArrayBuffer 中的数据,不同于 Typed Arrays,它可以手动指定数据的类型和字节偏移量。

当使用 ArrayBufferTypedArrayDataView 时,以下是一些简单的示例代码:

ArrayBuffer 示例:

代码语言:javascript
复制
// 创建一个包含 8 个字节的 ArrayBuffer
const buffer = new ArrayBuffer(8);

// 获取 ArrayBuffer 的字节长度
const byteLength = buffer.byteLength;

// 输出字节长度
console.log(`Byte Length: ${byteLength}`);

TypedArray 示例:

代码语言:javascript
复制
// 使用 Int32Array 来操作 ArrayBuffer
const buffer = new ArrayBuffer(8);
const int32Array = new Int32Array(buffer);

// 设置第一个元素的值
int32Array[0] = 42;

// 获取第二个元素的值(注意,这里使用了 Int32Array,所以一个元素占据 4 个字节)
const secondValue = int32Array[1];

console.log(`First Element: ${int32Array[0]}`);
console.log(`Second Element: ${secondValue}`);

DataView 示例:

代码语言:javascript
复制
// 创建一个包含 8 个字节的 ArrayBuffer
const buffer = new ArrayBuffer(8);

// 使用 DataView 来操作 ArrayBuffer
const dataView = new DataView(buffer);

// 设置第一个 32 位整数(字节偏移量为 0)
dataView.setInt32(0, 42);

// 获取第二个 32 位整数(字节偏移量为 4)
const secondValue = dataView.getInt32(4);

console.log(`First Element: ${dataView.getInt32(0)}`);
console.log(`Second Element: ${secondValue}`);

这些示例演示了如何创建 ArrayBuffer,使用 TypedArray 来访问和修改其数据,以及如何使用 DataView 进行更灵活的操作。请注意,TypedArrayDataView 是 ArrayBuffer 的视图,它们提供了不同的方法来处理底层数据。

数据类型之间的转换和数据读写

当涉及到数据的处理和转换时,Blob、File 和 ArrayBuffer 提供了一些方法来读取、写入和转换数据。

数据读写

  1. 从 Blob 或 File 中读取数据:
    1. 使用 FileReader 对象,它提供了读取文件内容的方法,比如 readAsText()readAsArrayBuffer()readAsDataURL() 等。
代码语言:javascript
复制
const file = /* 获取的 File 对象 */;
const reader = new FileReader();
reader.onload = function(event) {const result = event.target.result;// 使用读取的数据进行操作
};
reader.readAsText(file); // 以文本格式读取文件内容
  1. 从 ArrayBuffer 中读取数据:
    1. 使用 TypedArrays 或 DataView 对象,它们允许你以不同数据类型(比如整数、浮点数)读取和写入 ArrayBuffer 中的数据。
代码语言:javascript
复制
const buffer = /* 获取的 ArrayBuffer 对象 */;
const view = new DataView(buffer);

const value = view.getInt16(0); // 从偏移量为 0 的位置读取一个整数值

数据转换

  1. Blob 转换为 ArrayBuffer:
    1. 使用 FileReader 对象的 readAsArrayBuffer() 方法,将 Blob 或 File 对象中的数据转换为 ArrayBuffer。
代码语言:javascript
复制
const blob = /* 获取的 Blob 对象 */;
const reader = new FileReader();
reader.onload = function(event) {const arrayBuffer = event.target.result;// 使用转换后的 ArrayBuffer 进行操作
};
reader.readAsArrayBuffer(blob); // 将 Blob 转换为 ArrayBuffer
  1. ArrayBuffer 转换为 Blob:
    1. 使用 ArrayBuffer 对象创建一个新的 Blob 对象,传入 ArrayBuffer 和相应的 MIME 类型。
代码语言:javascript
复制
const arrayBuffer = /* 获取的 ArrayBuffer 对象 */;
const blob = new Blob([arrayBuffer], { type: 'application/octet-stream' });

这些方法可以帮助你从 Blob、File 和 ArrayBuffer 中读取和写入数据,以及在不同格式间进行转换。这在处理文件、图像、音频或视频等二进制数据时非常有用。

暂时无法在飞书文档外展示此内容

网页中的流

在前端开发中,Stream API 是一组用于处理数据流的功能接口,用于处理输入和输出流的数据。HTML5 中引入了一些与流相关的 API,让开发者可以更方便地操作数据流。

Streams API 概览:

1. ReadableStream(可读流): `ReadableStream` 表示一种可读取的数据流。它允许开发者从各种数据源(例如网络请求、文件、Blob 对象等)读取数据。

代码语言:javascript
复制
   // 创建一个可读流
   const stream = new ReadableStream({
     start(controller) {
       // 从某个数据源生成数据并通过 controller.enqueue() 发送
     },
     pull(controller) {
       // 当需要更多数据时调用,可以在这里继续发送数据
     },
     cancel(reason) {
       // 在流被取消时执行的操作
     }
   });
   ```

2. WritableStream(可写流): `WritableStream` 用于写入数据流。它提供了一个接口,可以将数据写入到目标中。

代码语言:javascript
复制
   // 创建一个可写流
   const writableStream = new WritableStream({
     write(chunk) {
       // 将数据写入到目标中
     },
     close() {
       // 在流关闭时执行的操作
     },
     abort(reason) {
       // 在流被中止时执行的操作
     }
   });
   ```

3. TransformStream(转换流): `TransformStream` 是一个通过对输入流进行处理生成输出流的接口,允许对数据进行转换、过滤或修改等操作。

代码语言:javascript
复制
   // 创建一个转换流
   const transformStream = new TransformStream({
     start(controller) {
       // 初始化转换流
     },
     transform(chunk, controller) {
       // 对输入数据进行转换处理,并通过 controller.enqueue() 发送输出数据
     },
     flush(controller) {
       // 在数据处理完成后执行的操作
     }
   });
   ```

这些 API 提供了一种灵活的方式来处理数据流,可以用于各种场景,例如从网络请求中读取数据、处理文件流、实现流式传输等。在实际应用中,开发者可以利用这些 API 进行数据处理、转换、过滤等操作,从而更高效地处理大量数据而无需等待整个数据加载完成。

常见从网页中创建流的方式:

浏览器中直接内置了许多有用的视频流。您可以轻松地从 blob 创建 ReadableStreamBlob 接口的 stream() 方法会返回一个 ReadableStream,在读取时,该方法会返回 blob 中包含的数据。另外请注意,File 对象是 Blob 的特定类型,可以在 blob 支持的任何上下文中使用。

代码语言:javascript
复制
const readableStream = new Blob(['hello world'], { type: 'text/plain' }).stream();

TextDecoder.decode()TextEncoder.encode() 的流式传输变体分别称为 TextDecoderStreamTextEncoderStream

代码语言:javascript
复制
const response = await fetch('https://streams.spec.whatwg.org/');
const decodedStream = response.body.pipeThrough(new TextDecoderStream());

使用分别使用 CompressionStreamDecompressionStream 转换流可以轻松压缩或解压缩文件。以下代码示例展示了如何下载 Streams 规范,直接在浏览器中对其进行压缩 (gzip),以及将压缩后的文件直接写入磁盘。

代码语言:javascript
复制
const response = await fetch('https://streams.spec.whatwg.org/');
const readableStream = response.body;
const compressedStream = readableStream.pipeThrough(new CompressionStream('gzip'));

const fileHandle = await showSaveFilePicker();
const writableStream = await fileHandle.createWritable();
compressedStream.pipeTo(writableStream);

例如,File System Access APIFileSystemWritableFileStream 和实验性 fetch() 请求流就是可写流的示例。

Serial API 大量使用了可读流和可写数据流。

代码语言:javascript
复制
// Prompt user to select any serial port.
const port = await navigator.serial.requestPort();
// Wait for the serial port to open.
await port.open({ baudRate: 9_600 });
const reader = port.readable.getReader();

// Listen to data coming from the serial device.
while (true) {
  const { value, done } = await reader.read();
  if (done) {
    // Allow the serial port to be closed later.
    reader.releaseLock();
    break;
  }
  // value is a Uint8Array.
  console.log(value);
}

// Write to the serial port.
const writer = port.writable.getWriter();
const data = new Uint8Array([104, 101, 108, 108, 111]); // hello
await writer.write(data);
// Allow the serial port to be closed later.
writer.releaseLock();

最后,WebSocketStream API 将数据流与 WebSocket API 集成。

代码语言:javascript
复制
const wss = new WebSocketStream(WSS_URL);
const { readable, writable } = await wss.connection;
const reader = readable.getReader();
const writer = writable.getWriter();

while (true) {
  const { value, done } = await reader.read();
  if (done) {
    break;
  }
  const result = await process(value);
  await writer.write(result);
}
  1. Blob:Blob 接口代表了不可变的原始数据的类文件对象。它可以通过其 stream() 方法创建一个 ReadableStream。
  2. TextDecoderStream 和 TextEncoderStream:这些是对于 TextDecoder.decode() 和 TextEncoder.encode() 的流式传输变体,用于解码和编码文本数据。
  3. CompressionStream 和 DecompressionStream:这些是用于压缩或解压缩文件的转换流,通过 CompressionStream 进行压缩 (gzip)。
  4. File System Access API:提供了 FileSystemWritableFileStream,是一个可写流的示例,用于对文件系统进行访问。
  5. Serial API:利用可读流和可写数据流,允许访问和操作串行设备,如串行端口。
  6. WebSocketStream API:用于与 WebSocket API 集成的数据流,允许通过 WebSocket 进行数据传输。

下面是一个使用 Mermaid 绘制的流程图,展示了这些流相关的 API 和功能之间的关系:

这个关系图用于展示这些流相关 API 之间的关联,同时也指明了它们之间的一些交互和用途。

暂时无法在飞书文档外展示此内容

例子

  1. 读取文件类型

取得 Blob 对象以后,可以通过 FileReader 对象,读取 Blob 对象的内容,即文件内容。

FileReader 对象提供四个方法。将 Blob 对象作为参数传入,然后以指定的格式返回。

  • FileReader.readAsText():返回文本,需要指定文本编码,默认为 UTF-8。
  • FileReader.readAsArrayBuffer():返回 ArrayBuffer 对象。
  • FileReader.readAsDataURL():返回 Data URL。
  • FileReader.readAsBinaryString():返回原始的二进制字符串。

下面是 FileReader.readAsText() 方法的例子,用来读取文本文件:

代码语言:javascript
复制
// HTML 代码如下
// <input type='file' onchange='readfile(this.files[0])'></input>
// <pre id='output'></pre>
function readfile(f) {
  let reader = new FileReader();
  reader.readAsText(f);
  reader.onload = function () {
    let text = reader.result;
    let out = document.getElementById('output');
    out.innerHTML = '';
    out.appendChild(document.createTextNode(text));
  }
  reader.onerror = function(e) {
    console.log('Error', e);
  };
}

下面是 FileReader.readAsArrayBuffer() 方法的例子,用于读取二进制文件:

代码语言:javascript
复制
// HTML 代码如下
// <input type="file" onchange="typefile(this.files[0])"></input>
function typefile(file) {
  // 文件开头的四个字节,生成一个 Blob 对象
  let slice = file.slice(0, 4);
  let reader = new FileReader();
  // 读取这四个字节
  reader.readAsArrayBuffer(slice);
  reader.onload = function (e) {
    let buffer = reader.result;
    // 将这四个字节的内容,视作一个32位整数
    let view = new DataView(buffer);
    let magic = view.getUint32(0, false);
    // 根据文件的前四个字节,判断它的类型
    switch(magic) {
      case 0x89504E47: file.verified_type = 'image/png'; break;
      case 0x47494638: file.verified_type = 'image/gif'; break;
      case 0x25504446: file.verified_type = 'application/pdf'; break;
      case 0x504b0304: file.verified_type = 'application/zip'; break;
    }
    console.log(file.name, file.verified_type);
  };
}
  1. 使用Uint8ClampedArray操作图像

Uint8ClampedArray 是一个存储 8 位无符号整数的 JavaScript 数组,常用于处理图像数据。它保证数值在 0 到 255 范围内,特别适用于图像处理,因为它确保像素值有效且性能高效。

代码语言:javascript
复制
    // 获取图像像素数据
        const imageData = tempCtx.getImageData(0, 0, img.width, img.height);
        const data = imageData.data;

        // 转换为灰度图像
        for (let i = 0; i < data.length; i += 4) {
          const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
          data[i] = avg; // Red
          data[i + 1] = avg; // Green
          data[i + 2] = avg; // Blue
        }

        // 将修改后的像素数据放回临时 canvas
        tempCtx.putImageData(imageData, 0, 0);

调用 getImageData 方法时,它返回一个包含图像数据的 ImageData 对象。ImageData 对象中的 data 属性是一个 Uint8ClampedArray,它包含了图像的像素数据。

在这个例子中,我们首先获取了原始图像的像素数据 data。这个数据是一个 Uint8ClampedArray,每个像素占据四个连续的位置(分别是红、绿、蓝和 alpha 通道,每个通道占一个字节)。所以 data 中的长度是图像宽度乘以图像高度乘以 4。

接着,我们对每个像素进行灰度化处理,将 RGB 三个通道的值取平均值,这样就得到了灰度值。在 Uint8ClampedArray 中,data[i] 是红色通道的值,data[i + 1] 是绿色通道的值,data[i + 2] 是蓝色通道的值,data[i + 3] 是 alpha 通道的值。因此,通过将 RGB 三个通道的值设置为相同的灰度值,我们将图像转换为灰度图像。

最后,我们通过 putImageData 方法将修改后的像素数据重新放回了 tempCtx,这样就在临时 canvas 上得到了灰度图像。

暂时无法在飞书文档外展示此内容

  1. 下载application/octet-stream类型的文件

当后端返回 application/octet-stream 类型的数据时,通常表示这是一种通用的二进制数据类型,可能是文件或其他二进制数据,比如图片、音频、视频等。前端可以通过以下方式处理并下载这种类型的数据:

使用 Fetch API 下载数据:

代码语言:javascript
复制
fetch('your_endpoint_url')
  .then(response => response.blob())
  .then(blobData => {
    // 创建一个 URL 对象
    const blobUrl = URL.createObjectURL(blobData);
    // 创建一个 <a> 元素
    const link = document.createElement('a');
    link.href = blobUrl;
    link.download = 'file_name'; // 下载文件时保存的文件名// 将 <a> 元素添加到页面中并触发下载document.body.appendChild(link);
    link.click();
// 下载完成后移除 <a> 元素和 URL 对象
    document.body.removeChild(link);
    URL.revokeObjectURL(blobUrl);
  })
  .catch(error => {console.error('下载出错:', error);
  });

这段代码通过 Fetch API 获取数据,然后将其转换为 Blob 对象。接着,利用 URL.createObjectURL() 创建了一个 URL,并将其赋给 <a> 元素的 href 属性。设置 download 属性可以指定下载文件时的文件名。最后,通过模拟点击 <a> 元素来触发下载。

附录

  1. binaryType

binaryType 是 WebSocket 对象的属性,它用于指定在通过 WebSocket 接收或发送二进制数据时的处理方式。这个属性有两个可能的值:

  1. "blob": 表示接收到的数据将会作为 Blob 对象处理。Blob 是一种表示二进制数据的对象,它可以是图片、音频或其他二进制文件的容器。
  2. "arraybuffer": 表示接收到的数据将会作为 ArrayBuffer 对象处理。ArrayBuffer 是一种用于表示通用的、固定长度的原始二进制数据的对象。它提供了一种可以存储任意类型的二进制数据的方式。

设置 binaryType 可以影响通过 WebSocket 发送和接收数据的方式。如果您期望接收到的数据是 Blob 对象,可以将 binaryType 设置为 "blob";如果希望数据以 ArrayBuffer 对象的形式接收,则将其设置为 "arraybuffer"。

例如,在 JavaScript 中,您可以这样设置 binaryType 属性:

代码语言:javascript
复制
// 创建 WebSocket 连接
const socket = new WebSocket('ws://example.com');
// 设置 binaryType
socket.binaryType = 'arraybuffer'; // 或者 'blob'

这对于处理 WebSocket 连接中的二进制数据非常有用,可以根据需要选择适合的数据类型来接收和处理数据。

  1. MIME类型

一些常见的 MIME 类型可以用于表示不同类型的数据:

  • 'image/jpeg':表示 JPEG 图像文件。
  • 'image/png':表示 PNG 图像文件。
  • 'application/pdf':表示 PDF 文档。
  • 'audio/mpeg':表示 MP3 音频文件。
  • 'video/mp4':表示 MP4 视频文件。
  • 'application/json':表示 JSON 数据。
  • 'application/xml':表示 XML 数据。
  • 'application/octet-stream': 表示二进制数据

我正在参与2024腾讯技术创作特训营第五期有奖征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
    • 为什么二进制数据重要?
      • 概述概念
      • Blob 和 File 的关系:
        • Blob创建方式
          • 语法
          • 参数
        • File构造方式
          • 语法
          • 参数
          • 示例
      • ArrayBuffer和DataView以及TypedArrays之间的关系
        • ArrayBuffer 示例:
          • TypedArray 示例:
            • DataView 示例:
            • 数据类型之间的转换和数据读写
              • 数据读写
                • 数据转换
                • 网页中的流
                  • Streams API 概览:
                    • 常见从网页中创建流的方式:
                    • 例子
                    • 附录
                    相关产品与服务
                    容器服务
                    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档