|
1 | 1 | # @aws-sdk/lib-storage/s3-transfer-manager |
2 | 2 |
|
| 3 | +[](https://www.npmjs.com/package/@aws-sdk/lib-storage) |
| 4 | +[](https://www.npmjs.com/package/@aws-sdk/lib-storage) |
| 5 | + |
3 | 6 | ## Overview |
4 | 7 |
|
5 | | -S3TransferManager is a high level library that helps customer interact with S3 |
| 8 | +S3TransferManager is a high level library that helps customers interact with S3 |
6 | 9 | for their most common use cases that involve multiple API operations through SDK JS V3. |
7 | 10 | S3TransferManager provides the following features: |
8 | 11 |
|
9 | | -- automatic multipart upload to S3 |
10 | | -- automatic multipart download from S3 |
11 | | -- upload all files in a directory to an S3 bucket recursively or non-recursively |
12 | | -- download all objects in a bucket to a local directory recursively or non-recursively |
13 | | -- transfer progress listener |
| 12 | +- automatic [multipart upload](#upload) to S3 |
| 13 | +- automatic [multipart download](#download) from S3 |
| 14 | +- upload all files in a directory to an S3 bucket recursively or non-recursively (see [upload all](#uploadall)) |
| 15 | +- download all objects in a bucket to a local directory recursively or non-recursively (see [download all](#downloadall)) |
| 16 | +- transfer progress listener (see [Event Listeners](#event-listeners)) |
14 | 17 |
|
15 | 18 | ## Installation |
16 | 19 |
|
| 20 | +`npm install @aws-sdk/lib-storage` |
| 21 | + |
17 | 22 | ## Getting Started |
18 | 23 |
|
19 | | -## Configuration |
| 24 | +### Import |
20 | 25 |
|
21 | | -When creating an instance of the S3TransferManager, users can configure some of it's client options |
22 | | -to best fit their use case. |
23 | | - |
24 | | -- s3ClientInstance - specify the low level S3 client that will be used to send reqeusts to S3 |
25 | | -- targetPartSizeBytes - specify the target part size to use in mulitpart transfer. Does not |
26 | | - apply to the last part and downloads if multipartDownloadType is PART |
27 | | -- multipartUploadThresholdBytes - specify the size threshold in bytes for multipart upload. |
28 | | -- checksumValidationEnabled - option to disable checksum validation for donwload. |
29 | | -- multipartDownloadType - specify how the SDK should perform multipart download. Either RANGE or PART. |
30 | | -- eventListeners - transfer progress listeners to receive event-driven updates on transfer |
31 | | - progress throughout the lifecycle of a request at client level. Supported callbacks: |
32 | | - - transferInitiated: A new transfer has been initiated. This method is invoked exactly once per |
33 | | - transfer, right after the operation has started. It allows users to retrieve the request and ProgressSnapshot. |
34 | | - - bytesTransferred: Additional bytes have been submitted or received. This method may be called |
35 | | - many times per transfer, depending on the transfer size and I/O buffer sizes. It must be called |
36 | | - at least once for a successful transfer. It allows users to retrieve the the request and the ProgressSnapshot. |
37 | | - - transferComplete: The transfer has completed successfully. This method is called exactly once for |
38 | | - a successful transfer. It allows users to retrieve the request, the response and the ProgressSnapshot. |
39 | | - - transferFailed: The transfer has failed. This method is called exactly once for a failed transfer. |
40 | | - It allows users to retrieve the request and a progress snapshot. |
41 | | - |
42 | | -### Example |
| 26 | +To begin using `S3TransferManager`, you must import it through `@aws-sdk/lib-storage`. You can also specify your own `S3Client` to use with `S3TransferManager`. Example: |
43 | 27 |
|
44 | 28 | ```js |
45 | 29 | import { S3Client } from "@aws-sdk/client-s3"; |
46 | 30 | import { S3TransferManager } from "@aws-sdk/lib-storage"; |
| 31 | +``` |
47 | 32 |
|
48 | | - const tm = new S3TransferManager ({ |
49 | | - s3ClientInstance: new S3Client({}), |
50 | | - multipartDownloadType: "RANGE", |
51 | | - targetPartSizeBytes: 8 * 1024 * 1024 |
52 | | - multipartThresholdBytes: 16 * 1024 * 1024, |
53 | | - checksumValidationEnabled: true, |
54 | | - checksumAlgorithm: CRC32, |
55 | | - multipartDownloadType: PART, |
56 | | - eventListeners: { |
57 | | - transferInitiated: [transferStarted], |
58 | | - bytesTrnasferred: [progressBar], |
59 | | - transferComplete: [{ |
60 | | - handleEvent: console.log({ |
61 | | - request, snapshot, response |
62 | | - }) |
63 | | - }], |
64 | | - trasnferFailed: [transferFailed] |
65 | | - } |
66 | | - }) |
| 33 | +### Creating a TransferManager Instance |
| 34 | + |
| 35 | +When creating an instance, takes an optional `S3TransferManagerConfig` object (see [Constructor Options](#constructor-options)). Minimal instantiation of a `S3TransferManager`: |
| 36 | + |
| 37 | +```js |
| 38 | +// Create S3 client |
| 39 | +const s3Client = new S3Client({ region: "us-east-1" }); |
| 40 | + |
| 41 | +// Create transfer manager |
| 42 | +const tm = new S3TransferManager({ |
| 43 | + s3ClientInstance: s3Client, |
| 44 | +}); |
| 45 | +``` |
| 46 | + |
| 47 | +### Basic Usage |
| 48 | + |
| 49 | +Basic use of `download()` (await required): |
| 50 | + |
| 51 | +```js |
| 52 | +const download = await tm.download({ |
| 53 | + Bucket, |
| 54 | + Key, |
| 55 | +}); |
| 56 | + |
| 57 | +const data = await download.Body?.transformToByteArray(); |
| 58 | +console.log(`Downloaded ${data.byteLength} bytes`); |
67 | 59 | ``` |
68 | 60 |
|
| 61 | +## Configuration |
| 62 | +
|
| 63 | +- **s3ClientInstance** - The S3 client instance to use for requests |
| 64 | +- **targetPartSizeBytes** - Target part size for multipart transfers (default: 8MB) |
| 65 | +- **multipartUploadThresholdBytes** - Size threshold for multipart upload (default: 16MB) |
| 66 | +- **checksumValidationEnabled** - Enable/disable checksum validation for downloads (default: true) |
| 67 | +- **multipartDownloadType** - Download strategy: "RANGE" or "PART" (default: "RANGE") |
| 68 | +- [**eventListeners**](#event-listeners) - Transfer progress listeners |
| 69 | +
|
69 | 70 | ### Constructor Options |
70 | 71 |
|
71 | | -## API Reference |
| 72 | +The S3TransferManager constructor accepts an optional `S3TransferManagerConfig` object with the following optional properties: |
| 73 | +
|
| 74 | +| Option | Type | Default | Description | |
| 75 | +| ------------------------------- | ------------------------ | ------------------------------------- | ------------------------------------------------- | |
| 76 | +| `s3ClientInstance` | `S3Client` | `new S3Client()` with checksum config | S3 client instance for API calls | |
| 77 | +| `targetPartSizeBytes` | `number` | `8388608` (8MB) | Target size for each part in multipart operations | |
| 78 | +| `multipartUploadThresholdBytes` | `number` | `16777216` (16MB) | File size threshold to trigger multipart upload | |
| 79 | +| `checksumValidationEnabled` | `boolean` | `true` | Enable checksum validation for data integrity | |
| 80 | +| `checksumAlgorithm` | `ChecksumAlgorithm` | `"CRC32"` | Algorithm used for checksum calculation | |
| 81 | +| `multipartDownloadType` | `"PART" \| "RANGE"` | `"PART"` | Strategy for multipart downloads | |
| 82 | +| `eventListeners` | `TransferEventListeners` | `{}` | Event listeners for transfer progress | |
| 83 | +
|
| 84 | +**Example:** |
| 85 | +
|
| 86 | +```js |
| 87 | +const transferManager = new S3TransferManager({ |
| 88 | + s3ClientInstance: new S3Client({ region: "us-west-2" }), |
| 89 | + targetPartSizeBytes: 10 * 1024 * 1024, // 10MB |
| 90 | + multipartUploadThresholdBytes: 20 * 1024 * 1024, // 20MB |
| 91 | + checksumValidationEnabled: false, |
| 92 | + checksumAlgorithm: "SHA256", |
| 93 | + multipartDownloadType: "RANGE", |
| 94 | + eventListeners: { |
| 95 | + transferInitiated: [myInitiatedHandler], |
| 96 | + bytesTransferred: [myProgressHandler], |
| 97 | + }, |
| 98 | +}); |
| 99 | +``` |
72 | 100 |
|
73 | 101 | ## Methods |
74 | 102 |
|
75 | 103 | ### upload() |
76 | 104 |
|
77 | 105 | ### download() |
78 | 106 |
|
79 | | -The download() function in S3TransferManager is a wrapper function for the S3 GetObjectCommand |
80 | | -allowing users to download objects from an S3 bucket using multipart download of two types |
81 | | -which are specified in the configuration of the S3TransferManager instance: Part GET and Ranged GET. |
82 | | -Both of which download the object using GetObjectCommand in separate streams then join them into |
83 | | -one single stream. The S3TransferManager download() supports Readable and ReadableStream for node and browser. |
| 107 | +Downloads objects from S3 using multipart download with two modes: |
| 108 | +
|
| 109 | +**PART Mode:** |
| 110 | +
|
| 111 | +- Optimized for objects uploaded via multipart upload |
| 112 | +- Uses S3's native PartNumber parameter to download parts concurrently |
| 113 | +
|
| 114 | +**RANGE Mode:** |
| 115 | +
|
| 116 | +- Works with any S3 object regardless of upload method |
| 117 | +- Uses HTTP Range headers to split objects into chunks for concurrent download |
| 118 | +
|
| 119 | +Both modes join separate streams into a single stream and support Readable/ReadableStream for Node.js and browsers. |
| 120 | +
|
| 121 | +**Parameters:** |
| 122 | +
|
| 123 | +- `Bucket` (required) - S3 bucket name |
| 124 | +- `Key` (required) - Object key/path |
| 125 | +- `Range` - Byte range for partial downloads (e.g., "bytes=0-1023") |
| 126 | +
|
| 127 | +**Transfer Options:** |
84 | 128 |
|
85 | | -- Part GET |
86 | | - - Use case: Optimizes downloads for objects that were uploaded using the S3 multipart upload |
87 | | - - How it works: Uses the S3 native download feature with the PartNumber parameter. It fetches part 1 of the object to get the metadata then downloads the remaining parts concurrently. |
88 | | -- Range GET |
89 | | - - Use case: Allows for multipart download for any S3 object regardless of whether it was |
90 | | - uploaded using multipart upload or not |
91 | | - - How it works: Uses the HTTP Range request with the bytes=start-end headers to split objects into |
92 | | - chunks based on the user-provided byte range header, or if not included the MIN_PART_SIZE to make concurrent range requests. |
| 129 | +- `abortSignal` - AbortController signal for cancellation |
| 130 | +- `eventListeners` - Progress tracking callbacks |
93 | 131 |
|
94 | | -Users can also include an abortController allowing for cancellation mid download along |
95 | | -with eventListeners for the callbacks: 'transferInitiated', 'bytesTransferred', 'transferComplete', |
96 | | -and 'transferFailed' at client level and request level. 'bytesTransferred' provides progress updates per byte chunk during streaming. |
| 132 | +> For complete parameter list, see [GetObjectCommandInput](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/command/GetObjectCommand/) documentation. |
97 | 133 |
|
98 | | -#### Validation |
| 134 | +**Features:** |
99 | 135 |
|
100 | | -Both multipartDownloadTypes have methods that validates the bytes and ranges of the multipart download requests. In multipartDownloadType PART, bytes of the part boundaries in each concurrent request are checked for whether they match the expected byte boundaries. In multipartDownloadType RANGE, the byte ranges are checked for whether they match the expected ranges. An error is thrown on mismatches and all requests for download is cancelled. |
| 136 | +- AbortController support for cancellation |
| 137 | +- Event listeners: `transferInitiated`, `bytesTransferred`, `transferComplete`, `transferFailed` |
| 138 | +- ETag validation ensures object consistency during download |
| 139 | +- Automatic boundary/range validation with error handling |
101 | 140 |
|
102 | | -Both both PART and RANGE GET uses the S3 standard IfMatch header with the initial ETag for subsequent parts to ensure object version consistency during a download. |
| 141 | +**Validation:** |
| 142 | +
|
| 143 | +Both modes validate data integrity: |
| 144 | +
|
| 145 | +- **PART**: Validates part boundaries match expected byte ranges |
| 146 | +- **RANGE**: Validates byte ranges match expected values |
| 147 | +- Uses `IfMatch` header with initial ETag to ensure object consistency |
| 148 | +- Throws errors and cancels download on validation failures |
| 149 | +
|
| 150 | +We do not recommend updating the object you're downloading mid-download as this may throw a [Precondition Failed error](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/http-412-precondition-failed.html). |
103 | 151 |
|
104 | 152 | #### uploadAll() |
105 | 153 |
|
106 | 154 | #### downloadAll() |
107 | 155 |
|
108 | | -### Event Handling |
| 156 | +## Event Handling |
109 | 157 |
|
110 | | -#### addEventListener() |
| 158 | +### addEventListener() |
111 | 159 |
|
112 | | -#### removeEventListener() |
| 160 | +Registers event listeners for transfer lifecycle monitoring. It uses familiar EventTarget API patterns. |
113 | 161 |
|
114 | | -#### dispatchEvent() |
| 162 | +**Event Types:** |
115 | 163 |
|
116 | | -## Transfer Options |
| 164 | +- `transferInitiated` - Fired when transfer begins |
| 165 | +- `bytesTransferred` - Fired during transfer progress with each byte chunk transfer |
| 166 | +- `transferComplete` - Fired when transfer succeeds |
| 167 | +- `transferFailed` - Fired when transfer fails |
117 | 168 |
|
118 | | -### AbortSignal |
| 169 | +**Parameters:** |
119 | 170 |
|
120 | | -### Event Listeners |
| 171 | +- `type` - Event type to listen for |
| 172 | +- `callback` - Function or object with `handleEvent` method |
| 173 | +- `options` - Optional configuration: |
| 174 | + - `once: boolean` - Remove listener after first execution |
| 175 | + - `signal: AbortSignal` - Auto-remove listener when signal aborts |
| 176 | +
|
| 177 | +**Example:** |
| 178 | +
|
| 179 | +```js |
| 180 | +function progressBar({ request, snapshot }) { |
| 181 | + const percent = snapshot.totalBytes ? (snapshot.transferredBytes / snapshot.totalBytes) * 100 : 0; |
| 182 | + let barLength = percent / 2; |
| 183 | + let progressBar = "["; |
| 184 | + for (let i = 0; i < 50; i++) { |
| 185 | + if (barLength > 0) { |
| 186 | + progressBar += "#"; |
| 187 | + barLength--; |
| 188 | + } else { |
| 189 | + progressBar += "-"; |
| 190 | + } |
| 191 | + } |
| 192 | + progressBar += "]"; |
| 193 | + |
| 194 | + process.stdout.clearLine(0); |
| 195 | + process.stdout.cursorTo(0); |
| 196 | + process.stdout.write(`Downloading... ${progressBar} ${percent.toFixed(0)}%`); |
| 197 | +} |
| 198 | + |
| 199 | +transferManager.addEventListener("bytesTransferred", progressBar); |
| 200 | + |
| 201 | +// One-time listener |
| 202 | +transferManager.addEventListener( |
| 203 | + "transferComplete", |
| 204 | + (event) => { |
| 205 | + console.log(`\nTransfer completed: ${event.request.Key}`); |
| 206 | + }, |
| 207 | + { once: true } |
| 208 | +); |
| 209 | +``` |
| 210 | + |
| 211 | +### removeEventListener() |
121 | 212 |
|
122 | | -## Examples |
| 213 | +Removes a previously registered event listener from the specified event type. |
123 | 214 |
|
124 | | -### Basic Upload |
| 215 | +**Parameters:** |
125 | 216 |
|
126 | | -### Basic Download |
| 217 | +- `type` - Event type to stop listening for |
| 218 | +- `callback` - The exact function that was previously registered |
| 219 | +- `options` - Optional configuration (currently unused) |
127 | 220 |
|
128 | | -### Multipart Download |
| 221 | +**Example:** |
| 222 | + |
| 223 | +```js |
| 224 | +const progressHandler = (event) => console.log("Progress:", event.snapshot); |
| 225 | + |
| 226 | +transferManager.addEventListener("bytesTransferred", progressHandler); |
| 227 | +transferManager.removeEventListener("bytesTransferred", progressHandler); |
| 228 | +``` |
129 | 229 |
|
130 | | -### Event Handling |
| 230 | +### dispatchEvent() |
131 | 231 |
|
132 | | -### Abort Operations |
| 232 | +Dispatches events to registered listeners. Primarily used internally but available for custom event handling. |
| 233 | + |
| 234 | +**Parameters:** |
| 235 | + |
| 236 | +- `event` - Event object with `type` property matching registered listeners |
| 237 | + |
| 238 | +**Returns:** |
| 239 | + |
| 240 | +- `boolean` - Always returns `true` (follows EventTarget API) |
| 241 | + |
| 242 | +**Example:** |
| 243 | + |
| 244 | +```js |
| 245 | +const customEvent = new Event("transferInitiated"); |
| 246 | +customEvent.snapshot = { transferredBytes: 0, totalBytes: 1000 }; |
| 247 | +transferManager.dispatchEvent(customEvent); |
| 248 | +``` |
| 249 | + |
| 250 | +## Transfer Options |
| 251 | + |
| 252 | +### AbortSignal |
| 253 | + |
| 254 | +TODO: Include practical examples of using abortcontroller to cancel downloads |
| 255 | + |
| 256 | +### Event Listeners |
133 | 257 |
|
134 | | -## Performance Considerations |
| 258 | +TODO: Include examples of eventListeners are client level and request level |
135 | 259 |
|
136 | | -## Error Handling |
| 260 | +## Performance |
0 commit comments