You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* See CHANGELOG for v3.0.0
* removed get-stream
* enabled linter just for test.js & from.js
* Any blob part is acceptable (jsdoc)
since the default fallback is to cast unknown items into strings
* async stat version
* import from fs/promise instead
* Updated the Readme and code examples
* known differences, buffer.Blob support, private stream, more test
* require node 14
* use fetch v3
Copy file name to clipboardexpand all lines: README.md
+94-13
Original file line number
Diff line number
Diff line change
@@ -13,18 +13,95 @@ A Blob implementation in Node.js, originally from [node-fetch](https://github.co
13
13
npm install fetch-blob
14
14
```
15
15
16
+
<details>
17
+
<summary>Upgrading from 2x to 3x</summary>
18
+
19
+
Updating from 2 to 3 should be a breeze since there is not many changes to the blob specification.
20
+
The major cause of a major release is coding standards.
21
+
- internal WeakMaps was replaced with private fields
22
+
- internal Buffer.from was replaced with TextEncoder/Decoder
23
+
- internal buffers was replaced with Uint8Arrays
24
+
- CommonJS was replaced with ESM
25
+
- The node stream returned by calling `blob.stream()` was replaced with a simple generator function that yields Uint8Array (Breaking change)
26
+
(Read "Differences from other blobs" for more info.)
27
+
28
+
All of this changes have made it dependency free of any core node modules, so it would be possible to just import it using http-import from a CDN without any bundling
29
+
30
+
</details>
31
+
32
+
<details>
33
+
<summary>Differences from other Blobs</summary>
34
+
35
+
- Unlike NodeJS `buffer.Blob` (Added in: v15.7.0) and browser native Blob this polyfilled version can't be sent via PostMessage
36
+
- This blob version is more arbitrary, it can be constructed with blob parts that isn't a instance of itself
37
+
it has to look and behave as a blob to be accepted as a blob part.
38
+
- The benefit of this is that you can create other types of blobs that don't contain any internal data that has to be read in other ways, such as the `BlobDataItem` created in `from.js` that wraps a file path into a blob-like item and read lazily (nodejs plans to [implement this][fs-blobs] as well)
39
+
- The `blob.stream()` is the most noticeable differences. It returns a AsyncGeneratorFunction that yields Uint8Arrays
40
+
41
+
The reasoning behind `Blob.prototype.stream()` is that NodeJS readable stream
42
+
isn't spec compatible with whatwg streams and we didn't want to import the hole whatwg stream polyfill for node
43
+
or browserify NodeJS streams for the browsers and picking any flavor over the other. So we decided to opted out
44
+
of any stream and just implement the bear minium of what both streams have in common which is the asyncIterator
45
+
that both yields Uint8Array. this is the most isomorphic way with the use of `for-await-of` loops.
46
+
It would be redundant to convert anything to whatwg streams and than convert it back to
47
+
node streams since you work inside of Node.
48
+
It will probably stay like this until nodejs get native support for whatwg<sup>[1][https://github.com/nodejs/whatwg-stream]</sup> streams and whatwg stream add the node
49
+
equivalent for `Readable.from(iterable)`<sup>[2](https://github.com/whatwg/streams/issues/1018)</sup>
50
+
51
+
But for now if you really need a Node Stream then you can do so using this transformation
52
+
```js
53
+
import {Readable} from'stream'
54
+
conststream=Readable.from(blob.stream())
55
+
```
56
+
But if you don't need it to be a stream then you can just use the asyncIterator part of it that is isomorphic.
57
+
```js
58
+
forawait (constchunkofblob.stream()) {
59
+
console.log(chunk) // uInt8Array
60
+
}
61
+
```
62
+
If you need to make some feature detection to fix this different behavior
63
+
```js
64
+
if (Blob.prototype.stream?.constructor?.name==='AsyncGeneratorFunction') {
65
+
// not spec compatible, monkey patch it...
66
+
// (Alternative you could extend the Blob and use super.stream())
* with minium requirement. Its wrapped around a Blob as a blobPart
28
+
* so you have no direct access to this.
19
29
*
20
30
* @private
21
31
*/
22
32
classBlobDataItem{
33
+
#path;
34
+
#start;
35
+
23
36
constructor(options){
37
+
this.#path =options.path;
38
+
this.#start =options.start;
24
39
this.size=options.size;
25
-
this.path=options.path;
26
-
this.start=options.start||0;
27
-
this.mtime=options.mtime;
40
+
this.lastModified=options.lastModified
28
41
}
29
42
30
-
// Slicing arguments is first validated and formated
31
-
// to not be out of range by Blob.prototype.slice
43
+
/**
44
+
* Slicing arguments is first validated and formatted
45
+
* to not be out of range by Blob.prototype.slice
46
+
*/
32
47
slice(start,end){
33
48
returnnewBlobDataItem({
34
-
path: this.path,
35
-
start,
36
-
mtime: this.mtime,
37
-
size: end-start
49
+
path: this.#path,
50
+
lastModified: this.lastModified,
51
+
size: end-start,
52
+
start
38
53
});
39
54
}
40
55
41
-
stream(){
42
-
if(statSync(this.path).mtime>this.mtime){
56
+
async*stream(){
57
+
const{mtimeMs}=awaitstat(this.#path)
58
+
if(mtimeMs>this.lastModified){
43
59
thrownewDOMException('The requested file could not be read, typically due to permission problems that have occurred after a reference to a file was acquired.','NotReadableError');
0 commit comments