Handling Binary Data
1. Understanding Binary Data Types
| Type | Description |
|---|---|
ArrayBuffer | Raw fixed-length byte buffer |
TypedArray | Typed view onto buffer |
DataView | Endian-aware random access |
Blob | File-like immutable byte sequence |
SharedArrayBuffer | Cross-thread (needs COOP/COEP) |
2. Setting Binary Type
| Value | Best For |
|---|---|
"arraybuffer" | Parsing in JS immediately |
"blob" | Forwarding to <img>, Response, file save |
3. Creating ArrayBuffer
Example: Create + fill
const buf = new ArrayBuffer(16);
const u8 = new Uint8Array(buf);
u8.set([1,2,3,4]);
| API | Description |
|---|---|
new ArrayBuffer(n) | Allocate n bytes |
buf.byteLength | Size |
buf.slice(s,e) | Copy subrange |
buf.transfer() NEW | Zero-copy ownership transfer |
4. Using Typed Arrays
| View | Range |
|---|---|
Int8Array | -128..127 |
Uint8Array | 0..255 |
Uint8ClampedArray | 0..255 (saturating) |
Int16/Uint16 | ±32K / 0..65K |
Int32/Uint32 | ±2.1B / 0..4.2B |
Float32/Float64 | IEEE 754 |
BigInt64/BigUint64 | 64-bit ints |
5. Using DataView
Example: Endian control
const v = new DataView(buf);
v.setUint32(0, 0xCAFEBABE, false); // big-endian
const n = v.getUint32(0, false);
const f = v.getFloat32(4, true); // little-endian
| Method | Detail |
|---|---|
getUint8/16/32 | Unsigned int read |
setInt* | Signed int write |
getFloat32/64 | IEEE 754 |
getBigUint64 | 64-bit |
6. Sending Binary Data
| Source | Sent As |
|---|---|
ArrayBuffer | Binary frame |
Uint8Array | Binary frame |
Blob | Binary frame (streamed) |
7. Receiving Binary Data
Example: Decode incoming
ws.binaryType = "arraybuffer";
ws.onmessage = (e) => {
const view = new DataView(e.data);
const opcode = view.getUint8(0);
dispatch(opcode, view);
};
| Step | Action |
|---|---|
| 1 | Set binaryType |
| 2 | Branch on typeof e.data |
| 3 | Wrap in DataView / TypedArray |
8. Converting Blob to ArrayBuffer
| Method | Returns |
|---|---|
blob.arrayBuffer() | Promise<ArrayBuffer> |
blob.bytes() NEW | Promise<Uint8Array> |
new Response(blob).arrayBuffer() | Same result |
FileReader.readAsArrayBuffer LEGACY | Pre-async alternative |
9. Implementing Binary Protocol
Example: TLV (type-length-value)
// frame: [u8 type][u16 len][len bytes value]
function frame(type, value) {
const out = new Uint8Array(3 + value.length);
out[0] = type;
new DataView(out.buffer).setUint16(1, value.length, false);
out.set(value, 3);
return out.buffer;
}
| Element | Width |
|---|---|
| Magic | 2-4 bytes |
| Version | 1 byte |
| Opcode | 1 byte |
| Length | 2/4 bytes |
| Payload | variable |
10. Handling Large Binary Files
| Approach | Detail |
|---|---|
| Chunking | Split into N-byte frames with seq |
| Streaming | Use WebSocketStream where supported |
| Hybrid | HTTP upload + WS notify URL |
| Resumable | Send offset markers, support range |
Warning: Browsers may impose memory caps; transferring multi-GB blobs through WS without streaming will OOM tabs.