eligrey / Blob.js

An HTML5 Blob implementation
Other
1.15k stars 605 forks source link

Time to include blob.text() blob.arrayBuffer() and blob.stream() #66

Closed jimmywarting closed 5 years ago

jimmywarting commented 5 years ago

I created this a long time ago and it's finally becoming real! (at least 3 things of them) https://github.com/jimmywarting/Screw-FileReader

var blob = Blob.prototype
var fullStreamSupport = false
var basicStreamSupport = false
var fetchTransform = false

function promisify(obj) {
  return new Promise(function(resolve, reject) {
    obj.onload =
    obj.onerror = function(evt) {
      obj.onload =
      obj.onerror = null

      evt.type === 'load'
        ? resolve(obj.result || obj)
        : reject(new Error('Failed to read the blob/file'))
    }
  })
}

try {
  new ReadableStream({})
  basicStreamSupport = true
} catch (e) {}

try {
  new ReadableStream({type: 'bytes'})
  fullStreamSupport = true
} catch (e) {}

try {
  (new Response(new Blob)).getReader()
  fetchTransform = true
} catch (e) {}

if (!blob.arrayBuffer) {
  blob.arrayBuffer = function arrayBuffer() {
    var fr = new FileReader
    fr.readAsArrayBuffer(this)
    return promisify(fr)
  }
}

if (!blob.text) {
  blob.text = function text() {
    var fr = new FileReader
    fr.readAsText(this)
    return promisify(fr)
  }
}

if (!blob.stream) {
  blob.stream =

  fullStreamSupport ? function stream() {
    var position = 0
    var blob = this

    return new ReadableStream({
      type: 'bytes',
      autoAllocateChunkSize: 524288,

      pull: function (controller) {
        var v = controller.byobRequest.view
        var chunk = blob.slice(position, position + v.byteLength)
        return chunk.arrayBuffer()
        .then(function (buffer) {
          var uint8array = new Uint8Array(buffer)
          var bytesRead = uint8array.byteLength

          position += bytesRead
          v.set(uint8array)
            controller.byobRequest.respond(bytesRead)

          if(position >= blob.size)
            controller.close()
        })
      }
    })
  }:

  // basic stream support
  basicStreamSupport ? function stream(blob){
    var position = 0
    var blob = this

    return new ReadableStream({
      pull: function (controller) {
        var chunk = blob.slice(position, position + 524288)

        return chunk.arrayBuffer().then(function (buffer) {
          position += buffer.byteLength
          var uint8array = new Uint8Array(buffer)
          controller.enqueue(uint8array)

          if (position == blob.size)
            controller.close()
        })
      }
    })
  }:

  // fetchTransform
  fetchTransform ? function stream() {
    return (new Response(this)).body
  }:

  function stream() {
    throw new Error('Include https://github.com/creatorrr/web-streams-polyfill')
  }
}