From 544a1d3546a2dee2f9901805ed70ac6f8c62030c Mon Sep 17 00:00:00 2001 From: David Frank Date: Thu, 16 May 2019 14:05:08 +0800 Subject: [PATCH] copy implementation from node-fetch --- blob.js | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 23 ++++++++++ 2 files changed, 142 insertions(+) create mode 100644 blob.js create mode 100644 package.json diff --git a/blob.js b/blob.js new file mode 100644 index 0000000..e1151a9 --- /dev/null +++ b/blob.js @@ -0,0 +1,119 @@ +// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js +// (MIT licensed) + +import Stream from 'stream'; + +// fix for "Readable" isn't a named export issue +const Readable = Stream.Readable; + +export const BUFFER = Symbol('buffer'); +const TYPE = Symbol('type'); + +export default class Blob { + constructor() { + this[TYPE] = ''; + + const blobParts = arguments[0]; + const options = arguments[1]; + + const buffers = []; + let size = 0; + + if (blobParts) { + const a = blobParts; + const length = Number(a.length); + for (let i = 0; i < length; i++) { + const element = a[i]; + let buffer; + if (element instanceof Buffer) { + buffer = element; + } else if (ArrayBuffer.isView(element)) { + buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength); + } else if (element instanceof ArrayBuffer) { + buffer = Buffer.from(element); + } else if (element instanceof Blob) { + buffer = element[BUFFER]; + } else { + buffer = Buffer.from(typeof element === 'string' ? element : String(element)); + } + size += buffer.length; + buffers.push(buffer); + } + } + + this[BUFFER] = Buffer.concat(buffers); + + let type = options && options.type !== undefined && String(options.type).toLowerCase(); + if (type && !/[^\u0020-\u007E]/.test(type)) { + this[TYPE] = type; + } + } + get size() { + return this[BUFFER].length; + } + get type() { + return this[TYPE]; + } + text() { + return Promise.resolve(this[BUFFER].toString()) + } + arrayBuffer() { + const buf = this[BUFFER]; + const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + return Promise.resolve(ab); + } + stream() { + const readable = new Readable(); + readable._read = () => {}; + readable.push(this[BUFFER]); + readable.push(null); + return readable; + } + toString() { + return '[object Blob]' + } + slice() { + const size = this.size; + + const start = arguments[0]; + const end = arguments[1]; + let relativeStart, relativeEnd; + if (start === undefined) { + relativeStart = 0; + } else if (start < 0) { + relativeStart = Math.max(size + start, 0); + } else { + relativeStart = Math.min(start, size); + } + if (end === undefined) { + relativeEnd = size; + } else if (end < 0) { + relativeEnd = Math.max(size + end, 0); + } else { + relativeEnd = Math.min(end, size); + } + const span = Math.max(relativeEnd - relativeStart, 0); + + const buffer = this[BUFFER]; + const slicedBuffer = buffer.slice( + relativeStart, + relativeStart + span + ); + const blob = new Blob([], { type: arguments[2] }); + blob[BUFFER] = slicedBuffer; + return blob; + } +} + +Object.defineProperties(Blob.prototype, { + size: { enumerable: true }, + type: { enumerable: true }, + slice: { enumerable: true } +}); + +Object.defineProperty(Blob.prototype, Symbol.toStringTag, { + value: 'Blob', + writable: false, + enumerable: false, + configurable: true +}); diff --git a/package.json b/package.json new file mode 100644 index 0000000..25e6374 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "fetch-blob", + "version": "1.0.0", + "description": "A Blob implementation on node.js, originally from node-fetch", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/bitinn/fetch-blob.git" + }, + "keywords": [ + "blob", + "node-fetch" + ], + "author": "David Frank", + "license": "MIT", + "bugs": { + "url": "https://github.com/bitinn/fetch-blob/issues" + }, + "homepage": "https://github.com/bitinn/fetch-blob#readme" +}