Skip to content

Commit 892736c

Browse files
committed
Document how to get better upload progress
Fixes #2420
1 parent c2ce656 commit 892736c

File tree

3 files changed

+66
-12
lines changed

3 files changed

+66
-12
lines changed

documentation/3-streams.md

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -124,27 +124,41 @@ An object representing how much data have been downloaded.
124124

125125
An object representing how much data have been uploaded.
126126

127-
**Note:**
128-
> - When a chunk is greater than `highWaterMark`, the progress won't be emitted. The body needs to be split into chunks.
127+
> **Note:** To get granular upload progress instead of just 0% and 100%, split the body into chunks using the [`chunk-data`](https://github.com/sindresorhus/chunk-data) package:
128+
> - `chunk(buffer, chunkSize)` - For buffers/typed arrays
129+
> - `chunkFromAsync(iterable, chunkSize)` - For iterables (Node.js streams are async iterables)
129130
130131
```js
131132
import got from 'got';
133+
import {chunk, chunkFromAsync} from 'chunk-data';
134+
import {Readable} from 'node:stream';
132135

133-
const body = Buffer.alloc(1024 * 1024); // 1MB
136+
// Chunk a buffer
134137

135-
function* chunkify(buffer, chunkSize = 64 * 1024) {
136-
for (let pos = 0; pos < buffer.byteLength; pos += chunkSize) {
137-
yield buffer.subarray(pos, pos + chunkSize)
138-
}
139-
}
138+
const buffer = new Uint8Array(1024 * 1024);
140139

141-
const stream = got.stream.post('https://httpbin.org/anything', {
142-
body: chunkify(body)
140+
await got.post('https://httpbin.org/anything', {
141+
body: chunk(buffer, 65_536),
142+
headers: {
143+
'content-length': buffer.byteLength.toString()
144+
}
145+
})
146+
.on('uploadProgress', progress => {
147+
console.log(progress);
143148
});
144149

145-
stream.resume();
146150

147-
stream.on('uploadProgress', progress => {
151+
// Chunk an iterable/stream
152+
153+
const [stream, size] = getStream();
154+
155+
await got.post('https://httpbin.org/anything', {
156+
body: chunkFromAsync(stream, 65_536),
157+
headers: {
158+
'content-length': size
159+
}
160+
})
161+
.on('uploadProgress', progress => {
148162
console.log(progress);
149163
});
150164
```

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
"bluebird": "^3.7.2",
8383
"body-parser": "^1.20.3",
8484
"c8": "^10.1.3",
85+
"chunk-data": "^0.1.0",
8586
"create-cert": "^1.0.6",
8687
"create-test-server": "^3.0.1",
8788
"del-cli": "^6.0.0",

test/progress.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import is from '@sindresorhus/is';
1313
import test, {type ExecutionContext} from 'ava';
1414
import type {Handler} from 'express';
1515
import {pEvent} from 'p-event';
16+
import {chunk, chunkFromAsync} from 'chunk-data';
1617
import type {Progress} from '../source/index.js';
1718
import withServer from './helpers/with-server.js';
1819

@@ -300,3 +301,41 @@ test('does not emit uploadProgress after cancelation', withServer, async (t, ser
300301

301302
t.pass();
302303
});
304+
305+
test('upload progress - chunk generator with buffer', withServer, async (t, server, got) => {
306+
server.post('/', uploadEndpoint);
307+
308+
const events: Progress[] = [];
309+
310+
await got.post({
311+
body: chunk(file, 65_536),
312+
headers: {
313+
'content-length': file.length.toString(),
314+
},
315+
})
316+
.on('uploadProgress', (event: Progress) => events.push(event));
317+
318+
checkEvents(t, events, file.length);
319+
320+
// Ensure we got more than just 0% and 100%
321+
t.true(events.length > 2, `Expected more than 2 events with chunk, got ${events.length}`);
322+
});
323+
324+
test('upload progress - chunkFromAsync async generator with stream', withServer, async (t, server, got) => {
325+
server.post('/', uploadEndpoint);
326+
327+
const events: Progress[] = [];
328+
329+
await got.post({
330+
body: chunkFromAsync(stream.Readable.from([file]), 65_536),
331+
headers: {
332+
'content-length': file.length.toString(),
333+
},
334+
})
335+
.on('uploadProgress', (event: Progress) => events.push(event));
336+
337+
checkEvents(t, events, file.length);
338+
339+
// Ensure we got more than just 0% and 100%
340+
t.true(events.length > 2, `Expected more than 2 events with chunkFromAsync, got ${events.length}`);
341+
});

0 commit comments

Comments
 (0)