skip to Main Content

Why does Blob() yield different results between passing an Array and a Uint8Array, when all values represent raw bytes?

new Blob([[0,60,0,60]])
// Blob {size: 9, type: ''}

new Blob([new Uint8Array([0,60,0,60])])
// Blob {size: 4, type: ''}

2

Answers


  1. TL;DR

    • Passing an Array of numbers ([[0,60,0,60]]) to the Blob constructor converts them to strings.
      • "0,60,0,60" size = 9
    • Passing an Uint8Array (new Uint8Array([0,60,0,60])) to the Blob constructor results in an internal BufferArray that represents the given Bytes.
      • [0, 60, 0, 60] size = 4

    Explanation

    The first Blob constructor parameters (W3) (blobParts) only support three different types:

    • BufferSource elements
    • Blob elements
    • USVString elements

    Input breakdown (Array)

    const blob = new Blob([[0, 60, 0, 60]]);
    console.log({ size: blob.size, type: blob.type });
    • The outer array [] is the blobParts sequence.
    • The inner array [0, 60, 0, 60] is a regular JavaScript array of numbers.
    • Regular Array of numbers: This is neither a BufferSource, Blob, nor a USVString. When the constructor encounters an unsupported type, it converts it to a string using the default toString() method (read 3 and 4).
    • Serialization: [0, 60, 0, 60].toString() results in the string "0,60,0,60".
    console.log([0,60,0,60].toString())
    console.log([0,60,0,60].toString().length)
    • The string "0,60,0,60" is treated as a USVString, encoded in UTF-8.
    • Size Calculation: Each character (including commas) occupies 1 byte in UTF-8, totaling 9 bytes.

    Input breakdown (Uint8Array)

    const blob = new Blob([new Uint8Array([0,60,0,60])])
    console.log({ size: blob.size, type: blob.type });
    • The array [new Uint8Array([0, 60, 0, 60])] is the blobParts sequence.
    • Uint8Array is a BufferSource.
    • BufferSource is an ArrayBuffer where each element corresponts to one byte. It is "An object that holds a pointer (which can be null) to a buffer of a fixed number of bytes"
    • Size Calculation: [0, 60, 0, 60] results in 4 bytes.
    console.log(new Uint8Array([0,60,0,60]))
    console.log(new Uint8Array([0,60,0,60]).length)
    Login or Signup to reply.
  2. The Blob constructor does not take an array of arrays as its argument. It takes an array of binary values – those might be buffers, blobs, typed arrays, or strings, but not arrays. The array you are passing is converted to a string, whose 9 characters are put as bytes into the blob:

    (async() => {
      console.log(new Uint8Array(await new Blob([[0,60,0,60]]).arrayBuffer()));
      console.log(new Uint8Array(await new Blob(["0,60,0,60"]).arrayBuffer()));
      /*
        0: 48 // '0'
        1: 44 // ','
        2: 54 // '6'
        3: 48 // '0'
        4: 44 // ','
        5: 48 // '0'
        6: 44 // ','
        7: 54 // '6'
        8: 48 // '0'
      */
    })();
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search