or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-objects.mdbucket-operations.mdclient-setup.mdindex.mdnotifications.mdobject-operations.mdpresigned-operations.mdtypes-and-errors.md

object-operations.mddocs/

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