@aws-sdk/lib-transfer-manager 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +303 -2
- package/dist-cjs/index.js +2 -0
- package/dist-cjs/submodules/transfer-manager/index.js +3166 -0
- package/dist-cjs/submodules/worker/index.js +579 -0
- package/dist-es/index.js +1 -0
- package/dist-es/submodules/transfer-manager/S3TransferManager.js +2229 -0
- package/dist-es/submodules/transfer-manager/chunker.js +115 -0
- package/dist-es/submodules/transfer-manager/directory-transfer-utils.js +102 -0
- package/dist-es/submodules/transfer-manager/event-listener-types.js +1 -0
- package/dist-es/submodules/transfer-manager/file-manager.js +70 -0
- package/dist-es/submodules/transfer-manager/index.browser.js +11 -0
- package/dist-es/submodules/transfer-manager/index.js +11 -0
- package/dist-es/submodules/transfer-manager/join-streams.browser.js +101 -0
- package/dist-es/submodules/transfer-manager/join-streams.js +105 -0
- package/dist-es/submodules/transfer-manager/log-level.js +30 -0
- package/dist-es/submodules/transfer-manager/ordered-part-queue.js +57 -0
- package/dist-es/submodules/transfer-manager/types.js +1 -0
- package/dist-es/submodules/transfer-manager/worker-http-handler.browser.js +25 -0
- package/dist-es/submodules/transfer-manager/worker-http-handler.js +453 -0
- package/dist-es/submodules/worker/http-request-worker.js +578 -0
- package/dist-es/submodules/worker/index.js +1 -0
- package/dist-types/index.d.ts +2 -0
- package/dist-types/submodules/transfer-manager/S3TransferManager.d.ts +60 -0
- package/dist-types/submodules/transfer-manager/chunker.d.ts +7 -0
- package/dist-types/submodules/transfer-manager/directory-transfer-utils.d.ts +90 -0
- package/dist-types/submodules/transfer-manager/event-listener-types.d.ts +54 -0
- package/dist-types/submodules/transfer-manager/file-manager.d.ts +51 -0
- package/dist-types/submodules/transfer-manager/index.browser.d.ts +10 -0
- package/dist-types/submodules/transfer-manager/index.d.ts +10 -0
- package/dist-types/submodules/transfer-manager/join-streams.browser.d.ts +21 -0
- package/dist-types/submodules/transfer-manager/join-streams.d.ts +26 -0
- package/dist-types/submodules/transfer-manager/log-level.d.ts +13 -0
- package/dist-types/submodules/transfer-manager/ordered-part-queue.d.ts +73 -0
- package/dist-types/submodules/transfer-manager/types.d.ts +473 -0
- package/dist-types/submodules/transfer-manager/worker-http-handler.browser.d.ts +20 -0
- package/dist-types/submodules/transfer-manager/worker-http-handler.d.ts +410 -0
- package/dist-types/submodules/worker/http-request-worker.d.ts +1 -0
- package/dist-types/submodules/worker/index.d.ts +1 -0
- package/dist-types/ts3.4/index.d.ts +2 -0
- package/dist-types/ts3.4/submodules/transfer-manager/S3TransferManager.d.ts +38 -0
- package/dist-types/ts3.4/submodules/transfer-manager/chunker.d.ts +10 -0
- package/dist-types/ts3.4/submodules/transfer-manager/directory-transfer-utils.d.ts +23 -0
- package/dist-types/ts3.4/submodules/transfer-manager/event-listener-types.d.ts +12 -0
- package/dist-types/ts3.4/submodules/transfer-manager/file-manager.d.ts +9 -0
- package/dist-types/ts3.4/submodules/transfer-manager/index.browser.d.ts +3 -0
- package/dist-types/ts3.4/submodules/transfer-manager/index.d.ts +3 -0
- package/dist-types/ts3.4/submodules/transfer-manager/join-streams.browser.d.ts +13 -0
- package/dist-types/ts3.4/submodules/transfer-manager/join-streams.d.ts +13 -0
- package/dist-types/ts3.4/submodules/transfer-manager/log-level.d.ts +13 -0
- package/dist-types/ts3.4/submodules/transfer-manager/ordered-part-queue.d.ts +18 -0
- package/dist-types/ts3.4/submodules/transfer-manager/types.d.ts +184 -0
- package/dist-types/ts3.4/submodules/transfer-manager/worker-http-handler.browser.d.ts +17 -0
- package/dist-types/ts3.4/submodules/transfer-manager/worker-http-handler.d.ts +241 -0
- package/dist-types/ts3.4/submodules/worker/http-request-worker.d.ts +1 -0
- package/dist-types/ts3.4/submodules/worker/index.d.ts +1 -0
- package/package.json +108 -4
- package/transfer-manager.d.ts +5 -0
- package/transfer-manager.js +5 -0
- package/worker.d.ts +5 -0
- package/worker.js +5 -0
package/README.md
CHANGED
|
@@ -1,3 +1,304 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @aws-sdk/lib-transfer-manager
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@aws-sdk/lib-transfer-manager)
|
|
4
|
+
[](https://www.npmjs.com/package/@aws-sdk/lib-transfer-manager)
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
Transfer Manager for S3 is a high-level data transfer utility built on top of the S3 client. It provides an API to transfer files and directories between your application and Amazon S3, and enables you to monitor a transfer's progress in real time. The Transfer Manager improves throughput by using parallel multipart transfers, dispatching work across worker threads when available, and optimizing DNS resolution to Amazon S3.
|
|
9
|
+
|
|
10
|
+
The following transfer operations are supported:
|
|
11
|
+
|
|
12
|
+
- [Upload an object](#upload-an-object) — seamlessly transitions between a single `PutObject` and a multipart upload (`CreateMultipartUpload` + `UploadPart`s + `CompleteMultipartUpload`) based on the object size.
|
|
13
|
+
- [Download an object](#download-an-object) — downloads large objects in parallel, by part or by byte-range.
|
|
14
|
+
- [Upload a directory](#upload-a-directory) — uploads all files under a local directory, recursively or non-recursively.
|
|
15
|
+
- [Downloading Objects to a directory](#downloading-objects-to-a-directory) — downloads all objects under a key prefix into a local directory, mapping the `/` key delimiter to subdirectories.
|
|
16
|
+
- [Transfer progress listeners](#monitor-transfer-progress) — monitor transfer lifecycle events in real time.
|
|
17
|
+
|
|
18
|
+
## ⚠️ Developer Preview
|
|
19
|
+
|
|
20
|
+
This library is currently in developer preview and is **NOT** recommended for production environments. It is meant for early access and feedback purposes at this time. We'd love to hear your feedback. See the AWS SDK and Tools [maintenance policy](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html#version-life-cycle)
|
|
21
|
+
descriptions for more information.
|
|
22
|
+
|
|
23
|
+
## Getting Started
|
|
24
|
+
|
|
25
|
+
### Installation
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
npm install @aws-sdk/lib-transfer-manager
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Instantiate the S3 Transfer Manager
|
|
32
|
+
|
|
33
|
+
You can instantiate the transfer manager using the default settings:
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
import { S3TransferManager } from "@aws-sdk/lib-transfer-manager";
|
|
37
|
+
|
|
38
|
+
const tm = new S3TransferManager();
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Or pass a config to customize it, including your own `S3Client`:
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
import { S3Client } from "@aws-sdk/client-s3";
|
|
45
|
+
import { S3TransferManager } from "@aws-sdk/lib-transfer-manager";
|
|
46
|
+
|
|
47
|
+
const tm = new S3TransferManager({
|
|
48
|
+
s3: new S3Client({ region: "us-west-2" }),
|
|
49
|
+
targetPartSizeBytes: 16 * 1024 * 1024, // 16 MB part size
|
|
50
|
+
maxConcurrentUploads: 256,
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
For the full list of configuration options, see the documentation comments on
|
|
55
|
+
[`S3TransferManagerConfig`](./src/submodules/transfer-manager/types.ts).
|
|
56
|
+
|
|
57
|
+
## Usage Examples
|
|
58
|
+
|
|
59
|
+
### Upload an object
|
|
60
|
+
|
|
61
|
+
Provide a request with the destination `Bucket`, `Key`, and `Body`. When the body is larger than
|
|
62
|
+
`multipartUploadThresholdBytes` (16 MB default), the transfer manager splits it into parts of
|
|
63
|
+
`targetPartSizeBytes` (8 MB default) and uploads them concurrently using S3
|
|
64
|
+
[multipart upload](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html).
|
|
65
|
+
|
|
66
|
+
You can monitor the progress of the transfer by attaching event listeners (see
|
|
67
|
+
[monitor transfer progress](#monitor-transfer-progress)).
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
import { createReadStream, statSync } from "node:fs";
|
|
71
|
+
|
|
72
|
+
const path = "file-to-upload.txt";
|
|
73
|
+
|
|
74
|
+
await tm.upload({
|
|
75
|
+
Bucket: "destination-bucket",
|
|
76
|
+
Key: "key-1",
|
|
77
|
+
Body: createReadStream(path),
|
|
78
|
+
ContentLength: statSync(path).size,
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### Zero-copy shared-memory uploads (Node.js)
|
|
83
|
+
|
|
84
|
+
For a multipart upload where the data is already in memory, pass a `Uint8Array`
|
|
85
|
+
or `Buffer` backed by a `SharedArrayBuffer`. Worker threads read part ranges
|
|
86
|
+
directly from that buffer, avoiding the transfer manager's normal whole-body
|
|
87
|
+
copy into shared memory.
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
const sharedBuffer = new SharedArrayBuffer(objectSize);
|
|
91
|
+
const body = Buffer.from(sharedBuffer);
|
|
92
|
+
|
|
93
|
+
// Fill body before starting the upload.
|
|
94
|
+
await tm.upload({
|
|
95
|
+
Bucket: "destination-bucket",
|
|
96
|
+
Key: "key-1",
|
|
97
|
+
Body: body,
|
|
98
|
+
ContentLength: body.byteLength,
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Do not mutate the shared buffer until the upload completes.
|
|
103
|
+
|
|
104
|
+
### Download an object
|
|
105
|
+
|
|
106
|
+
Provide a request with the source `Bucket` and `Key`. The response `Body` is a single joined
|
|
107
|
+
stream. Objects larger than a single part are downloaded in parts concurrently, using either part
|
|
108
|
+
numbers or byte ranges as configured by `multipartDownloadType` (`"PART"` by default).
|
|
109
|
+
|
|
110
|
+
- **PART** (default) — downloads the object using its part numbers. The object must have been
|
|
111
|
+
uploaded with multipart upload for a part-based download to split it into multiple parts;
|
|
112
|
+
otherwise it is downloaded as a single part.
|
|
113
|
+
- **RANGE** — downloads the object using HTTP byte-range requests, so it works for any object
|
|
114
|
+
regardless of how it was uploaded.
|
|
115
|
+
|
|
116
|
+
Same as upload, you can monitor the progress of the transfer by attaching event listeners (see
|
|
117
|
+
[monitor transfer progress](#monitor-transfer-progress)).
|
|
118
|
+
|
|
119
|
+
```js
|
|
120
|
+
const download = await tm.download({
|
|
121
|
+
Bucket: "source-bucket",
|
|
122
|
+
Key: "some-key",
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const data = await download.Body?.transformToByteArray();
|
|
126
|
+
console.log(`Downloaded ${data.byteLength} bytes`);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
To use RANGE mode, set `multipartDownloadType: "RANGE"` on the transfer manager. You still request
|
|
130
|
+
the whole object the same way, the transfer manager issues the internal byte-range requests for
|
|
131
|
+
you, so you do not set any `Range` header yourself:
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
const tm = new S3TransferManager({
|
|
135
|
+
s3: new S3Client({ region: "us-west-2" }),
|
|
136
|
+
multipartDownloadType: "RANGE",
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const download = await tm.download({
|
|
140
|
+
Bucket: "source-bucket",
|
|
141
|
+
Key: "some-key",
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const data = await download.Body?.transformToByteArray();
|
|
145
|
+
console.log(`Downloaded ${data.byteLength} bytes`);
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
To download only part of an object, set the `Range` header on the request. This works with `multipartDownloadType` and returns just the requested bytes:
|
|
149
|
+
|
|
150
|
+
```js
|
|
151
|
+
// Download the first 5 MB only
|
|
152
|
+
const download = await tm.download({
|
|
153
|
+
Bucket: "source-bucket",
|
|
154
|
+
Key: "some-key",
|
|
155
|
+
Range: "bytes=0-5242879",
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const data = await download.Body?.transformToByteArray();
|
|
159
|
+
console.log(`Downloaded ${data.byteLength} bytes`);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
To download directly to a local file instead of buffering the stream, use `downloadToFile`. By
|
|
163
|
+
default an existing file at `destination` is overwritten; set `failIfExists: true` to fail instead:
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
const result = await tm.downloadToFile({
|
|
167
|
+
Bucket: "source-bucket",
|
|
168
|
+
Key: "some-key",
|
|
169
|
+
destination: "./downloads/some-key",
|
|
170
|
+
failIfExists: true, // throws if ./downloads/some-key already exists (default: false, overwrite)
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
console.log(`Wrote ${result.bytesWritten} bytes`);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Upload a directory
|
|
177
|
+
|
|
178
|
+
Provide the destination `bucket` and the local `source` directory. Each file is uploaded as an object whose key is its path relative to `source`, using `/` as the separator, so subdirectory separators become part of the S3 object key. By default the directory is not traversed recursively; set `recursive: true` to include subdirectories.
|
|
179
|
+
|
|
180
|
+
```js
|
|
181
|
+
const result = await tm.uploadDirectory({
|
|
182
|
+
bucket: "destination-bucket",
|
|
183
|
+
source: "source/directory/to/upload",
|
|
184
|
+
recursive: true,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
console.log(`Uploaded ${result.objectsUploaded}, failed ${result.objectsFailed}`);
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
By default, if any individual object fails, the whole directory transfer stops and the error is
|
|
191
|
+
thrown (`failurePolicy: "terminate"`). Set `failurePolicy: "continue"` to skip failed objects and
|
|
192
|
+
keep going — the failures are reflected in `objectsFailed`. You can also pass a callback to decide
|
|
193
|
+
per failure:
|
|
194
|
+
|
|
195
|
+
```js
|
|
196
|
+
const result = await tm.uploadDirectory({
|
|
197
|
+
bucket: "destination-bucket",
|
|
198
|
+
source: "source/directory/to/upload",
|
|
199
|
+
recursive: true,
|
|
200
|
+
failurePolicy: async ({ objectRequest, error }) => {
|
|
201
|
+
console.warn(`Failed ${objectRequest.Key}: ${error}`);
|
|
202
|
+
return "continue";
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Downloading Objects to a directory
|
|
208
|
+
|
|
209
|
+
Download the objects under a bucket to a local `destination` directory. The `/` delimiter in each object key is mapped to local subdirectories. Provide the source `bucket` and the destination directory; optionally filter which objects are downloaded with
|
|
210
|
+
`s3Prefix` or a `filter` callback.
|
|
211
|
+
|
|
212
|
+
```js
|
|
213
|
+
const result = await tm.downloadDirectory({
|
|
214
|
+
bucket: "source-bucket",
|
|
215
|
+
destination: "destination/directory/for/download",
|
|
216
|
+
s3Prefix: "photos/",
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
console.log(`Downloaded ${result.objectsDownloaded}, failed ${result.objectsFailed}`);
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Like `uploadDirectory`, per-object failures are governed by `failurePolicy` (`"terminate"` by
|
|
223
|
+
default, or `"continue"`, or a callback). See [Upload a directory](#upload-a-directory) for the
|
|
224
|
+
failure-policy details.
|
|
225
|
+
|
|
226
|
+
### Monitor transfer progress
|
|
227
|
+
|
|
228
|
+
Ypu can attach listeners for the transfer lifecycle events — `transferInitiated` (fires once when a
|
|
229
|
+
transfer begins), `bytesTransferred` (fires as data moves), `transferComplete` (fires once on
|
|
230
|
+
success), and `transferFailed` (fires once on failure). Each listener receives an event with the
|
|
231
|
+
original `request`, a progress `snapshot`, and — for `transferComplete` — the S3 `response`.
|
|
232
|
+
|
|
233
|
+
Listeners can be set at the **client level** (in the constructor, applying to every transfer) or
|
|
234
|
+
at the **request level** (added on top of the client-level listeners for that one transfer).
|
|
235
|
+
|
|
236
|
+
```js
|
|
237
|
+
const onInitiated = ({ request }) => console.log(`Started: ${request.Key}`);
|
|
238
|
+
|
|
239
|
+
const onProgress = ({ snapshot }) => {
|
|
240
|
+
const percent = snapshot.totalBytes ? (snapshot.transferredBytes / snapshot.totalBytes) * 100 : 0;
|
|
241
|
+
console.log(`Progress: ${percent.toFixed(1)}%`);
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
const onComplete = ({ request, snapshot }) => {
|
|
245
|
+
console.log(`Completed: ${request.Key} (${snapshot.transferredBytes} bytes)`);
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
const onFailed = ({ request }) => console.log(`Failed: ${request.Key}`);
|
|
249
|
+
|
|
250
|
+
// Client-level: applies to every transfer made by this instance
|
|
251
|
+
const tm = new S3TransferManager({
|
|
252
|
+
eventListeners: {
|
|
253
|
+
transferInitiated: [onInitiated],
|
|
254
|
+
bytesTransferred: [onProgress],
|
|
255
|
+
transferComplete: [onComplete],
|
|
256
|
+
transferFailed: [onFailed],
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Request-level: added on top of the client-level listeners for this transfer only
|
|
261
|
+
await tm.download(
|
|
262
|
+
{ Bucket: "source-bucket", Key: "some-key" },
|
|
263
|
+
{
|
|
264
|
+
eventListeners: {
|
|
265
|
+
transferComplete: [({ request }) => console.log(`Done: ${request.Key}`)],
|
|
266
|
+
},
|
|
267
|
+
}
|
|
268
|
+
);
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
You can also register and remove listeners after construction with `addEventListener` /
|
|
272
|
+
`removeEventListener` (an `EventTarget`-style API):
|
|
273
|
+
|
|
274
|
+
```js
|
|
275
|
+
tm.addEventListener("bytesTransferred", onProgress);
|
|
276
|
+
|
|
277
|
+
// Fire only once, then auto-remove
|
|
278
|
+
tm.addEventListener("transferComplete", onComplete, { once: true });
|
|
279
|
+
|
|
280
|
+
// To remove a listener later, pass the same function reference used to add it.
|
|
281
|
+
// (Anonymous inline functions cannot be removed.)
|
|
282
|
+
tm.removeEventListener("bytesTransferred", onProgress);
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Transfers can be cancelled with a standard `AbortController` via `transferOptions.abortSignal`:
|
|
286
|
+
|
|
287
|
+
```js
|
|
288
|
+
const controller = new AbortController();
|
|
289
|
+
const timeoutId = setTimeout(() => controller.abort(), 30_000);
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
const download = await tm.download({ Bucket: "source-bucket", Key: "some-key" }, { abortSignal: controller.signal });
|
|
293
|
+
const data = await download.Body?.transformToByteArray();
|
|
294
|
+
console.log(`Downloaded ${data.byteLength} bytes`);
|
|
295
|
+
} catch (error) {
|
|
296
|
+
if (error.name === "AbortError") {
|
|
297
|
+
console.log("Download aborted");
|
|
298
|
+
} else {
|
|
299
|
+
throw error;
|
|
300
|
+
}
|
|
301
|
+
} finally {
|
|
302
|
+
clearTimeout(timeoutId);
|
|
303
|
+
}
|
|
304
|
+
```
|