0
# Object Operations
1
2
This document covers basic object operations including upload, download, copy, delete, and metadata management. For advanced features like multipart uploads, object composition, and S3 Select, see [Advanced Objects](./advanced-objects.md).
3
4
## Object Upload Operations
5
6
### Put Object (Stream/Buffer/String)
7
8
```javascript { .api }
9
const uploadInfo = await client.putObject(bucketName, objectName, stream, size?, metaData?)
10
11
// Parameters
12
bucketName: string // Bucket name
13
objectName: string // Object name/key
14
stream: stream.Readable | Buffer | string // Data to upload
15
size?: number // Data size (optional, auto-detected for Buffer/string)
16
metaData?: ItemBucketMetadata // Object metadata
17
18
// Returns: Promise<UploadedObjectInfo>
19
```
20
21
#### ItemBucketMetadata Type
22
23
```typescript { .api }
24
interface ItemBucketMetadata {
25
[key: string]: any // Custom metadata (prefixed with 'x-amz-meta-')
26
27
// Standard HTTP headers (not prefixed)
28
'Content-Type'?: string
29
'Content-Encoding'?: string
30
'Content-Disposition'?: string
31
'Content-Language'?: string
32
'Cache-Control'?: string
33
'Expires'?: string
34
}
35
```
36
37
#### UploadedObjectInfo Interface
38
39
```typescript { .api }
40
interface UploadedObjectInfo {
41
etag: string // Object ETag
42
versionId?: string // Version ID (if versioning enabled)
43
}
44
```
45
46
#### Upload Examples
47
48
```javascript { .api }
49
import * as fs from 'node:fs'
50
import * as path from 'node:path'
51
52
// Upload from string
53
const uploadInfo = await client.putObject(
54
'my-bucket',
55
'hello.txt',
56
'Hello, World!',
57
undefined, // size auto-detected
58
{ 'Content-Type': 'text/plain' }
59
)
60
61
// Upload from Buffer
62
const buffer = Buffer.from('Binary data', 'utf8')
63
await client.putObject('my-bucket', 'data.bin', buffer)
64
65
// Upload from stream with metadata
66
const stream = fs.createReadStream('/path/to/file.pdf')
67
const stat = fs.statSync('/path/to/file.pdf')
68
69
await client.putObject('my-bucket', 'document.pdf', stream, stat.size, {
70
'Content-Type': 'application/pdf',
71
'Content-Disposition': 'attachment; filename="document.pdf"',
72
'x-amz-meta-author': 'John Doe',
73
'x-amz-meta-category': 'reports'
74
})
75
```
76
77
### Put Object from File
78
79
```javascript { .api }
80
const uploadInfo = await client.fPutObject(bucketName, objectName, filePath, metaData?)
81
82
// Parameters
83
bucketName: string // Bucket name
84
objectName: string // Object name/key
85
filePath: string // Local file path
86
metaData?: ObjectMetaData // Object metadata
87
88
// Returns: Promise<UploadedObjectInfo>
89
```
90
91
#### Examples
92
93
```javascript { .api }
94
// Simple file upload
95
await client.fPutObject('my-bucket', 'photo.jpg', './photos/vacation.jpg')
96
97
// File upload with metadata
98
await client.fPutObject('my-bucket', 'report.pdf', './documents/report.pdf', {
99
'Content-Type': 'application/pdf',
100
'x-amz-meta-department': 'finance',
101
'x-amz-meta-year': '2023'
102
})
103
```
104
105
## Object Download Operations
106
107
### Get Object (Stream)
108
109
```javascript { .api }
110
const stream = await client.getObject(bucketName, objectName, getOpts?)
111
112
// Parameters
113
bucketName: string // Bucket name
114
objectName: string // Object name/key
115
getOpts?: GetObjectOpts // Download options
116
117
// Returns: Promise<stream.Readable>
118
```
119
120
#### GetObjectOpts Interface
121
122
```typescript { .api }
123
interface GetObjectOpts {
124
versionId?: string // Specific version ID
125
SSECustomerAlgorithm?: string // Server-side encryption algorithm (AES256)
126
SSECustomerKey?: string // Server-side encryption key
127
SSECustomerKeyMD5?: string // MD5 hash of encryption key
128
}
129
```
130
131
#### Download Examples
132
133
```javascript { .api }
134
import * as fs from 'node:fs'
135
136
// Download object to stream
137
const stream = await client.getObject('my-bucket', 'hello.txt')
138
let content = ''
139
stream.on('data', chunk => content += chunk)
140
stream.on('end', () => console.log('Content:', content))
141
142
// Download and save to file
143
const downloadStream = await client.getObject('my-bucket', 'photo.jpg')
144
const writeStream = fs.createWriteStream('./downloaded-photo.jpg')
145
downloadStream.pipe(writeStream)
146
147
// Download specific version
148
const versionStream = await client.getObject('my-bucket', 'document.pdf', {
149
versionId: 'ABC123DEF456'
150
})
151
152
// Download with server-side encryption
153
const encryptedStream = await client.getObject('my-bucket', 'secret.txt', {
154
SSECustomerAlgorithm: 'AES256',
155
SSECustomerKey: 'your-32-char-secret-key-here!!',
156
SSECustomerKeyMD5: 'MD5-hash-of-key'
157
})
158
```
159
160
### Get Partial Object
161
162
```javascript { .api }
163
const stream = await client.getPartialObject(bucketName, objectName, offset, length?, getOpts?)
164
165
// Parameters
166
bucketName: string // Bucket name
167
objectName: string // Object name/key
168
offset: number // Byte offset to start from
169
length?: number // Number of bytes to read (optional, reads to end)
170
getOpts?: GetObjectOpts // Download options
171
172
// Returns: Promise<stream.Readable>
173
```
174
175
#### Partial Download Examples
176
177
```javascript { .api }
178
// Download first 1024 bytes
179
const partialStream = await client.getPartialObject('my-bucket', 'large-file.dat', 0, 1024)
180
181
// Download from offset 1000 to end of file
182
const tailStream = await client.getPartialObject('my-bucket', 'large-file.dat', 1000)
183
184
// Download specific byte range
185
const middleStream = await client.getPartialObject('my-bucket', 'large-file.dat', 5000, 2048)
186
```
187
188
### Get Object to File
189
190
```javascript { .api }
191
await client.fGetObject(bucketName, objectName, filePath, getOpts?)
192
193
// Parameters
194
bucketName: string // Bucket name
195
objectName: string // Object name/key
196
filePath: string // Local file path to save
197
getOpts?: GetObjectOpts // Download options
198
199
// Returns: Promise<void>
200
```
201
202
#### Examples
203
204
```javascript { .api }
205
// Download to local file
206
await client.fGetObject('my-bucket', 'report.pdf', './downloads/report.pdf')
207
208
// Download specific version to file
209
await client.fGetObject('my-bucket', 'document.txt', './versions/document-v1.txt', {
210
versionId: 'version-123'
211
})
212
```
213
214
## Object Information Operations
215
216
### Get Object Metadata
217
218
```javascript { .api }
219
const stat = await client.statObject(bucketName, objectName, statOpts?)
220
221
// Parameters
222
bucketName: string // Bucket name
223
objectName: string // Object name/key
224
statOpts?: StatObjectOpts // Stat options
225
226
// Returns: Promise<BucketItemStat>
227
```
228
229
#### StatObjectOpts Interface
230
231
```typescript { .api }
232
interface StatObjectOpts {
233
versionId?: string // Specific version ID
234
SSECustomerAlgorithm?: string // Server-side encryption algorithm
235
SSECustomerKey?: string // Server-side encryption key
236
SSECustomerKeyMD5?: string // MD5 hash of encryption key
237
}
238
```
239
240
#### BucketItemStat Interface
241
242
```typescript { .api }
243
interface BucketItemStat {
244
size: number // Object size in bytes
245
etag: string // Object ETag
246
lastModified: Date // Last modified timestamp
247
metaData: ResponseHeader // Object metadata and headers
248
versionId?: string // Version ID (if versioning enabled)
249
isDeleteMarker?: boolean // True if this is a delete marker
250
}
251
```
252
253
#### Metadata Examples
254
255
```javascript { .api }
256
// Get object metadata
257
const stat = await client.statObject('my-bucket', 'photo.jpg')
258
console.log('Size:', stat.size)
259
console.log('ETag:', stat.etag)
260
console.log('Last Modified:', stat.lastModified)
261
console.log('Content Type:', stat.metaData['content-type'])
262
console.log('Custom Meta:', stat.metaData['x-amz-meta-author'])
263
264
// Get metadata for specific version
265
const versionStat = await client.statObject('my-bucket', 'document.pdf', {
266
versionId: 'version-456'
267
})
268
```
269
270
## Object Listing Operations
271
272
### List Objects (V1)
273
274
```javascript { .api }
275
const objectStream = client.listObjects(bucketName, prefix?, recursive?, listOpts?)
276
277
// Parameters
278
bucketName: string // Bucket name
279
prefix?: string // Object prefix filter
280
recursive?: boolean // List recursively (default: false)
281
listOpts?: ListObjectQueryOpts // Additional options
282
283
// Returns: BucketStream<ObjectInfo>
284
```
285
286
### List Objects V2
287
288
```javascript { .api }
289
const objectStream = client.listObjectsV2(bucketName, prefix?, recursive?, startAfter?)
290
291
// Parameters
292
bucketName: string // Bucket name
293
prefix?: string // Object prefix filter
294
recursive?: boolean // List recursively (default: false)
295
startAfter?: string // Start listing after this object name
296
297
// Returns: stream.Readable
298
```
299
300
### List Objects V2 Query (Advanced)
301
302
```javascript { .api }
303
const objectStream = client.listObjectsV2Query(bucketName, prefix, continuationToken, delimiter, maxKeys, startAfter)
304
305
// Parameters
306
bucketName: string // Bucket name
307
prefix: string // Object prefix filter
308
continuationToken: string // Continuation token for pagination
309
delimiter: string // Delimiter for grouping keys
310
maxKeys: number // Maximum number of keys to return
311
startAfter: string // Start listing after this object name
312
313
// Returns: stream.Readable
314
```
315
316
#### ObjectInfo Interface
317
318
```typescript { .api }
319
interface ObjectInfo {
320
name: string // Object name/key
321
prefix?: string // Object prefix (for grouped results)
322
size: number // Object size in bytes
323
etag?: string // Object ETag
324
lastModified: Date // Last modified timestamp
325
storageClass?: string // Storage class
326
isDir?: boolean // True if this represents a directory
327
}
328
```
329
330
#### Listing Examples
331
332
```javascript { .api }
333
// List all objects
334
const objectStream = client.listObjects('my-bucket')
335
objectStream.on('data', obj => {
336
console.log('Object:', obj.name, 'Size:', obj.size)
337
})
338
objectStream.on('error', err => console.error('Error:', err))
339
objectStream.on('end', () => console.log('Listing complete'))
340
341
// List objects with prefix
342
const photosStream = client.listObjects('my-bucket', 'photos/', true)
343
photosStream.on('data', obj => {
344
if (!obj.isDir) {
345
console.log('Photo:', obj.name, 'Modified:', obj.lastModified)
346
}
347
})
348
349
// List objects V2 (recommended)
350
const objectStreamV2 = client.listObjectsV2('my-bucket', 'documents/', true)
351
objectStreamV2.on('data', obj => {
352
console.log('Document:', obj.name, 'Storage Class:', obj.storageClass)
353
})
354
355
// Advanced listing with full control (listObjectsV2Query)
356
const advancedStream = client.listObjectsV2Query(
357
'my-bucket', // bucketName
358
'logs/', // prefix
359
'', // continuationToken (empty for first page)
360
'/', // delimiter (for directory-style listing)
361
1000, // maxKeys
362
'logs/2023/' // startAfter
363
)
364
advancedStream.on('data', obj => {
365
console.log('Advanced listing:', obj.name)
366
})
367
368
// Collect all objects into array
369
function listAllObjects(bucketName, prefix) {
370
return new Promise((resolve, reject) => {
371
const objects = []
372
const stream = client.listObjects(bucketName, prefix, true)
373
374
stream.on('data', obj => objects.push(obj))
375
stream.on('error', reject)
376
stream.on('end', () => resolve(objects))
377
})
378
}
379
380
const allObjects = await listAllObjects('my-bucket', 'data/')
381
```
382
383
## Object Copy Operations
384
385
### Copy Object
386
387
```javascript { .api }
388
const result = await client.copyObject(source, dest)
389
390
// Parameters
391
source: CopySourceOptions // Source object configuration
392
dest: CopyDestinationOptions // Destination object configuration
393
394
// Returns: Promise<CopyObjectResult>
395
```
396
397
For detailed information about `CopySourceOptions` and `CopyDestinationOptions`, see [Advanced Objects](./advanced-objects.md#copy-operations).
398
399
#### Simple Copy Example
400
401
```javascript { .api }
402
import { CopySourceOptions, CopyDestinationOptions } from 'minio'
403
404
// Simple object copy
405
const source = new CopySourceOptions({
406
Bucket: 'source-bucket',
407
Object: 'source-object.jpg'
408
})
409
410
const dest = new CopyDestinationOptions({
411
Bucket: 'dest-bucket',
412
Object: 'copied-object.jpg'
413
})
414
415
const result = await client.copyObject(source, dest)
416
console.log('Copy ETag:', result.etag)
417
```
418
419
## Object Delete Operations
420
421
### Delete Single Object
422
423
```javascript { .api }
424
await client.removeObject(bucketName, objectName, removeOpts?)
425
426
// Parameters
427
bucketName: string // Bucket name
428
objectName: string // Object name/key
429
removeOpts?: RemoveOptions // Delete options
430
431
// Returns: Promise<void>
432
```
433
434
#### RemoveOptions Interface
435
436
```typescript { .api }
437
interface RemoveOptions {
438
versionId?: string // Specific version to delete
439
governanceBypass?: boolean // Bypass governance retention
440
}
441
```
442
443
### Delete Multiple Objects
444
445
```javascript { .api }
446
const results = await client.removeObjects(bucketName, objectsList)
447
448
// Parameters
449
bucketName: string // Bucket name
450
objectsList: RemoveObjectsParam // Objects to delete
451
452
// Returns: Promise<RemoveObjectsResponse[]>
453
```
454
455
#### RemoveObjectsParam Type
456
457
```typescript { .api }
458
type RemoveObjectsParam = string[] | RemoveObjectsRequestEntry[]
459
460
interface RemoveObjectsRequestEntry {
461
name: string // Object name
462
versionId?: string // Version ID (optional)
463
}
464
```
465
466
#### RemoveObjectsResponse Interface
467
468
```typescript { .api }
469
interface RemoveObjectsResponse {
470
name?: string // Object name
471
versionId?: string // Version ID
472
deleteMarker?: boolean // True if delete marker created
473
deleteMarkerVersionId?: string // Delete marker version ID
474
475
// Error information (if deletion failed)
476
errorCode?: string // Error code
477
errorMessage?: string // Error message
478
}
479
```
480
481
#### Delete Examples
482
483
```javascript { .api }
484
// Delete single object
485
await client.removeObject('my-bucket', 'old-file.txt')
486
487
// Delete specific version
488
await client.removeObject('my-bucket', 'versioned-file.txt', {
489
versionId: 'version-123'
490
})
491
492
// Delete multiple objects by name
493
const objectsToDelete = ['file1.txt', 'file2.jpg', 'file3.pdf']
494
const deleteResults = await client.removeObjects('my-bucket', objectsToDelete)
495
496
deleteResults.forEach(result => {
497
if (result.errorCode) {
498
console.error(`Failed to delete ${result.name}: ${result.errorMessage}`)
499
} else {
500
console.log(`Deleted: ${result.name}`)
501
}
502
})
503
504
// Delete multiple objects with versions
505
const objectsWithVersions = [
506
{ name: 'file1.txt', versionId: 'version-1' },
507
{ name: 'file2.txt', versionId: 'version-2' }
508
]
509
await client.removeObjects('my-bucket', objectsWithVersions)
510
```
511
512
### Remove Incomplete Upload
513
514
Removes an incomplete multipart upload from a bucket. This is useful for cleaning up failed or abandoned multipart uploads.
515
516
```javascript { .api }
517
await client.removeIncompleteUpload(bucketName, objectName)
518
519
// Parameters
520
bucketName: string // Bucket name
521
objectName: string // Object name/key of the incomplete upload
522
523
// Returns: Promise<void>
524
```
525
526
#### Examples
527
528
```javascript
529
// Remove incomplete upload for a specific object
530
try {
531
await client.removeIncompleteUpload('my-bucket', 'large-file.zip')
532
console.log('Incomplete upload removed successfully')
533
} catch (error) {
534
if (error.code === 'NoSuchUpload') {
535
console.log('No incomplete upload found for this object')
536
} else {
537
console.error('Error removing incomplete upload:', error)
538
}
539
}
540
541
// Clean up multiple incomplete uploads (use with listIncompleteUploads)
542
const incompleteStream = client.listIncompleteUploads('my-bucket')
543
incompleteStream.on('data', async (upload) => {
544
try {
545
await client.removeIncompleteUpload('my-bucket', upload.key)
546
console.log(`Cleaned up incomplete upload: ${upload.key}`)
547
} catch (error) {
548
console.error(`Failed to remove ${upload.key}:`, error.message)
549
}
550
})
551
```
552
553
## Object Tagging Operations
554
555
### Get Object Tags
556
557
```javascript { .api }
558
const tags = await client.getObjectTagging(bucketName, objectName, getOpts?)
559
560
// Parameters
561
bucketName: string // Bucket name
562
objectName: string // Object name/key
563
getOpts?: GetObjectOpts // Version and encryption options
564
565
// Returns: Promise<Tag[]>
566
```
567
568
### Set Object Tags
569
570
```javascript { .api }
571
await client.setObjectTagging(bucketName, objectName, tags, putOpts?)
572
573
// Parameters
574
bucketName: string // Bucket name
575
objectName: string // Object name/key
576
tags: Tags // Tags to set
577
putOpts?: TaggingOpts // Version options
578
579
// Returns: Promise<void>
580
```
581
582
### Remove Object Tags
583
584
```javascript { .api }
585
await client.removeObjectTagging(bucketName, objectName, removeOpts)
586
587
// Parameters
588
bucketName: string // Bucket name
589
objectName: string // Object name/key
590
removeOpts: TaggingOpts // Version options
591
592
// Returns: Promise<void>
593
```
594
595
#### TaggingOpts Interface
596
597
```typescript { .api }
598
interface TaggingOpts {
599
versionId?: string // Specific version ID
600
}
601
```
602
603
#### Tagging Examples
604
605
```javascript { .api }
606
// Set object tags
607
await client.setObjectTagging('my-bucket', 'document.pdf', {
608
'Category': 'Financial',
609
'Department': 'Accounting',
610
'Year': '2023'
611
})
612
613
// Get object tags
614
const tags = await client.getObjectTagging('my-bucket', 'document.pdf')
615
tags.forEach(tag => {
616
console.log(`${tag.Key}: ${tag.Value}`)
617
})
618
619
// Set tags on specific version
620
await client.setObjectTagging('my-bucket', 'versioned-doc.pdf', {
621
'Status': 'Archived'
622
}, { versionId: 'version-456' })
623
624
// Remove all tags
625
await client.removeObjectTagging('my-bucket', 'document.pdf', {})
626
```
627
628
## Error Handling
629
630
```javascript { .api }
631
import {
632
S3Error,
633
InvalidObjectNameError,
634
InvalidArgumentError
635
} from 'minio'
636
637
try {
638
await client.putObject('my-bucket', 'file.txt', 'content')
639
} catch (error) {
640
if (error instanceof S3Error) {
641
switch (error.code) {
642
case 'NoSuchBucket':
643
console.error('Bucket does not exist')
644
break
645
case 'AccessDenied':
646
console.error('Access denied to bucket or object')
647
break
648
case 'InvalidObjectName':
649
console.error('Invalid object name')
650
break
651
default:
652
console.error('S3 Error:', error.code, error.message)
653
}
654
} else if (error instanceof InvalidObjectNameError) {
655
console.error('Invalid object name format:', error.message)
656
}
657
}
658
```
659
660
## Best Practices
661
662
### 1. Object Naming
663
- Use forward slashes (/) for logical hierarchy
664
- Avoid special characters and spaces
665
- Use consistent naming conventions
666
- Consider sortability for listing operations
667
668
### 2. Upload Optimization
669
- Use streams for large files
670
- Set appropriate Content-Type metadata
671
- Use multipart uploads for files > 5MB (see [Advanced Objects](./advanced-objects.md))
672
- Consider compression for text-based content
673
674
### 3. Download Optimization
675
- Use partial downloads for large files when possible
676
- Stream data directly to destination instead of loading into memory
677
- Handle network interruptions with retry logic
678
- Consider caching frequently accessed objects
679
680
### 4. Metadata Management
681
- Use consistent metadata schemas
682
- Store searchable information in tags
683
- Keep metadata minimal to reduce overhead
684
- Document custom metadata conventions
685
686
### 5. Error Handling
687
- Always handle network timeouts
688
- Implement retry logic for transient errors
689
- Validate object names before operations
690
- Log errors with sufficient context for debugging
691
692
---
693
694
**Next:** [Advanced Objects](./advanced-objects.md) - Learn about multipart uploads, composition, and advanced features