0
# Container Client Operations
1
2
Container clients provide comprehensive functionality for managing blob containers, including creation, configuration, blob management, and access control.
3
4
## BlobContainerClient
5
6
The synchronous client for blob container operations.
7
8
### Creating Container Clients
9
10
```java
11
import com.azure.storage.blob.BlobContainerClient;
12
import com.azure.storage.blob.BlobContainerClientBuilder;
13
import com.azure.storage.blob.BlobServiceClient;
14
15
// From service client (recommended)
16
BlobServiceClient serviceClient = new BlobServiceClientBuilder()
17
.connectionString("DefaultEndpointsProtocol=https;AccountName=myaccount;...")
18
.buildClient();
19
BlobContainerClient containerClient = serviceClient.getBlobContainerClient("mycontainer");
20
21
// Direct creation using builder
22
BlobContainerClient containerClient = new BlobContainerClientBuilder()
23
.connectionString("DefaultEndpointsProtocol=https;AccountName=myaccount;...")
24
.containerName("mycontainer")
25
.buildClient();
26
27
// Using endpoint and credential
28
BlobContainerClient containerClient = new BlobContainerClientBuilder()
29
.endpoint("https://myaccount.blob.core.windows.net/mycontainer")
30
.credential(new DefaultAzureCredentialBuilder().build())
31
.buildClient();
32
```
33
34
### Container Lifecycle Management
35
36
```java
37
import com.azure.storage.blob.models.*;
38
import com.azure.core.http.rest.Response;
39
import com.azure.core.util.Context;
40
41
// Create container
42
containerClient.create();
43
44
// Create with options and metadata
45
Map<String, String> metadata = Map.of(
46
"environment", "production",
47
"team", "backend",
48
"created-by", "deployment-script"
49
);
50
51
BlobContainerCreateOptions createOptions = new BlobContainerCreateOptions()
52
.setMetadata(metadata)
53
.setPublicAccessType(PublicAccessType.BLOB);
54
55
Response<Void> createResponse = containerClient.createWithResponse(
56
createOptions,
57
Duration.ofSeconds(30),
58
Context.NONE
59
);
60
61
System.out.println("Container created, status: " + createResponse.getStatusCode());
62
63
// Create if not exists
64
boolean created = containerClient.createIfNotExists();
65
if (created) {
66
System.out.println("Container was created");
67
} else {
68
System.out.println("Container already exists");
69
}
70
71
// Check if container exists
72
Boolean exists = containerClient.exists();
73
System.out.println("Container exists: " + exists);
74
75
// Delete container
76
containerClient.delete();
77
78
// Delete with conditions
79
BlobRequestConditions conditions = new BlobRequestConditions()
80
.setIfUnmodifiedSince(OffsetDateTime.now().minusDays(1));
81
82
Response<Void> deleteResponse = containerClient.deleteWithResponse(
83
conditions,
84
Duration.ofSeconds(30),
85
Context.NONE
86
);
87
88
// Delete if exists
89
boolean deleted = containerClient.deleteIfExists();
90
```
91
92
### Container Properties and Metadata
93
94
```java
95
// Get container properties
96
BlobContainerProperties properties = containerClient.getProperties();
97
System.out.println("Last modified: " + properties.getLastModified());
98
System.out.println("ETag: " + properties.getETag());
99
System.out.println("Public access: " + properties.getPublicAccess());
100
System.out.println("Lease status: " + properties.getLeaseStatus());
101
System.out.println("Lease state: " + properties.getLeaseState());
102
System.out.println("Has immutability policy: " + properties.hasImmutabilityPolicy());
103
System.out.println("Has legal hold: " + properties.hasLegalHold());
104
System.out.println("Metadata: " + properties.getMetadata());
105
106
// Set metadata
107
Map<String, String> newMetadata = Map.of(
108
"environment", "staging",
109
"version", "2.0",
110
"last-updated", OffsetDateTime.now().toString()
111
);
112
113
containerClient.setMetadata(newMetadata);
114
115
// Set metadata with conditions
116
BlobRequestConditions metadataConditions = new BlobRequestConditions()
117
.setIfMatch(properties.getETag());
118
119
Response<Void> metadataResponse = containerClient.setMetadataWithResponse(
120
newMetadata,
121
metadataConditions,
122
Duration.ofSeconds(30),
123
Context.NONE
124
);
125
```
126
127
### Access Policies and Permissions
128
129
```java
130
import com.azure.storage.blob.models.*;
131
import java.time.OffsetDateTime;
132
import java.util.List;
133
import java.util.ArrayList;
134
135
// Get current access policy
136
BlobContainerAccessPolicies accessPolicies = containerClient.getAccessPolicy();
137
System.out.println("Public access: " + accessPolicies.getBlobAccessType());
138
139
for (BlobSignedIdentifier identifier : accessPolicies.getIdentifiers()) {
140
System.out.println("Policy ID: " + identifier.getId());
141
BlobAccessPolicy policy = identifier.getAccessPolicy();
142
System.out.println("Permissions: " + policy.getPermissions());
143
System.out.println("Start time: " + policy.getStartsOn());
144
System.out.println("Expiry time: " + policy.getExpiresOn());
145
}
146
147
// Set access policy with stored access policies
148
List<BlobSignedIdentifier> identifiers = new ArrayList<>();
149
150
BlobSignedIdentifier readOnlyPolicy = new BlobSignedIdentifier()
151
.setId("ReadOnlyAccess")
152
.setAccessPolicy(new BlobAccessPolicy()
153
.setPermissions("r")
154
.setStartsOn(OffsetDateTime.now())
155
.setExpiresOn(OffsetDateTime.now().plusDays(30)));
156
157
BlobSignedIdentifier fullAccessPolicy = new BlobSignedIdentifier()
158
.setId("FullAccess")
159
.setAccessPolicy(new BlobAccessPolicy()
160
.setPermissions("racwdl")
161
.setStartsOn(OffsetDateTime.now())
162
.setExpiresOn(OffsetDateTime.now().plusDays(7)));
163
164
identifiers.add(readOnlyPolicy);
165
identifiers.add(fullAccessPolicy);
166
167
// Apply access policies
168
containerClient.setAccessPolicy(PublicAccessType.CONTAINER, identifiers);
169
170
// Remove public access
171
containerClient.setAccessPolicy(null, identifiers);
172
```
173
174
### Blob Management
175
176
```java
177
// Get blob client
178
BlobClient blobClient = containerClient.getBlobClient("myfile.txt");
179
180
// Create blob client with snapshot
181
BlobClient snapshotClient = containerClient.getBlobClient("myfile.txt", "2023-12-01T10:30:00.1234567Z");
182
183
// Check if blob exists
184
boolean blobExists = blobClient.exists();
185
186
// Upload a simple blob
187
String content = "Hello, Azure Blob Storage!";
188
blobClient.upload(BinaryData.fromString(content), true); // overwrite if exists
189
190
// Upload with metadata and properties
191
Map<String, String> blobMetadata = Map.of("author", "system", "type", "log");
192
BlobHttpHeaders headers = new BlobHttpHeaders()
193
.setContentType("text/plain")
194
.setContentEncoding("utf-8")
195
.setCacheControl("no-cache");
196
197
BlobUploadFromFileOptions uploadOptions = new BlobUploadFromFileOptions("local-file.txt")
198
.setHeaders(headers)
199
.setMetadata(blobMetadata)
200
.setTags(Map.of("environment", "prod", "team", "backend"))
201
.setTier(AccessTier.HOT);
202
203
Response<BlockBlobItem> uploadResponse = blobClient.uploadFromFileWithResponse(
204
uploadOptions,
205
Duration.ofMinutes(5),
206
Context.NONE
207
);
208
```
209
210
### Listing Blobs
211
212
```java
213
import com.azure.core.http.rest.PagedIterable;
214
215
// List all blobs
216
PagedIterable<BlobItem> blobs = containerClient.listBlobs();
217
for (BlobItem blob : blobs) {
218
System.out.println("Blob: " + blob.getName());
219
System.out.println("Size: " + blob.getProperties().getContentLength() + " bytes");
220
System.out.println("Type: " + blob.getProperties().getBlobType());
221
System.out.println("Last Modified: " + blob.getProperties().getLastModified());
222
System.out.println("Access Tier: " + blob.getProperties().getAccessTier());
223
}
224
225
// List with options and filtering
226
ListBlobsOptions listOptions = new ListBlobsOptions()
227
.setPrefix("logs/2023/")
228
.setMaxResultsPerPage(100)
229
.setDetails(new BlobListDetails()
230
.setRetrieveDeletedBlobs(true)
231
.setRetrieveMetadata(true)
232
.setRetrieveTags(true)
233
.setRetrieveSnapshots(true)
234
.setRetrieveVersions(true)
235
.setRetrieveUncommittedBlobs(false));
236
237
PagedIterable<BlobItem> filteredBlobs = containerClient.listBlobs(listOptions, Duration.ofMinutes(2));
238
239
for (BlobItem blob : filteredBlobs) {
240
System.out.println("Blob: " + blob.getName());
241
System.out.println("Metadata: " + blob.getMetadata());
242
System.out.println("Tags: " + blob.getTags());
243
System.out.println("Is deleted: " + blob.isDeleted());
244
System.out.println("Is current version: " + blob.isCurrentVersion());
245
if (blob.getSnapshot() != null) {
246
System.out.println("Snapshot: " + blob.getSnapshot());
247
}
248
}
249
250
// Hierarchical listing (simulating folders)
251
String delimiter = "/";
252
PagedIterable<BlobItem> hierarchicalBlobs = containerClient.listBlobsByHierarchy(delimiter);
253
254
for (BlobItem item : hierarchicalBlobs) {
255
if (item.isPrefix()) {
256
System.out.println("Directory: " + item.getName());
257
} else {
258
System.out.println("File: " + item.getName());
259
}
260
}
261
262
// List with prefix and hierarchy
263
ListBlobsOptions hierarchicalOptions = new ListBlobsOptions()
264
.setPrefix("documents/2023/");
265
266
PagedIterable<BlobItem> folderBlobs = containerClient.listBlobsByHierarchy(
267
delimiter,
268
hierarchicalOptions,
269
Duration.ofMinutes(1)
270
);
271
```
272
273
### Finding Blobs by Tags
274
275
```java
276
// Find blobs in container using tag queries
277
String tagFilter = "environment='production' AND team='backend'";
278
PagedIterable<TaggedBlobItem> taggedBlobs = containerClient.findBlobsByTags(tagFilter);
279
280
for (TaggedBlobItem taggedBlob : taggedBlobs) {
281
System.out.println("Blob: " + taggedBlob.getName());
282
System.out.println("Tags: " + taggedBlob.getTags().toMap());
283
}
284
285
// Find with options
286
FindBlobsOptions findOptions = new FindBlobsOptions(tagFilter)
287
.setMaxResultsPerPage(50);
288
289
PagedIterable<TaggedBlobItem> pagedTaggedBlobs = containerClient.findBlobsByTags(
290
findOptions,
291
Duration.ofSeconds(30)
292
);
293
```
294
295
### Container SAS Generation
296
297
```java
298
import com.azure.storage.blob.sas.*;
299
import java.time.OffsetDateTime;
300
301
// Generate container-level SAS token
302
OffsetDateTime expiryTime = OffsetDateTime.now().plusHours(2);
303
304
BlobContainerSasPermission permission = new BlobContainerSasPermission()
305
.setReadPermission(true)
306
.setListPermission(true)
307
.setAddPermission(true)
308
.setCreatePermission(true);
309
310
BlobServiceSasSignatureValues sasValues = new BlobServiceSasSignatureValues(expiryTime, permission)
311
.setStartTime(OffsetDateTime.now())
312
.setProtocol(SasProtocol.HTTPS_ONLY)
313
.setSasIpRange(SasIpRange.parse("192.168.1.0/24"));
314
315
String containerSas = containerClient.generateSas(sasValues);
316
System.out.println("Container SAS: " + containerSas);
317
318
// Generate SAS with stored access policy
319
BlobServiceSasSignatureValues storedPolicySas = new BlobServiceSasSignatureValues()
320
.setIdentifier("ReadOnlyAccess"); // Reference to stored policy
321
322
String storedPolicySasToken = containerClient.generateSas(storedPolicySas);
323
```
324
325
## BlobContainerAsyncClient
326
327
The asynchronous client for blob container operations using reactive programming.
328
329
### Creating Async Container Clients
330
331
```java
332
import com.azure.storage.blob.BlobContainerAsyncClient;
333
import reactor.core.publisher.Mono;
334
import reactor.core.publisher.Flux;
335
336
// From async service client
337
BlobServiceAsyncClient asyncServiceClient = new BlobServiceClientBuilder()
338
.connectionString("DefaultEndpointsProtocol=https;AccountName=myaccount;...")
339
.buildAsyncClient();
340
BlobContainerAsyncClient asyncContainerClient = asyncServiceClient.getBlobContainerAsyncClient("mycontainer");
341
342
// Direct creation
343
BlobContainerAsyncClient asyncContainerClient = new BlobContainerClientBuilder()
344
.connectionString("DefaultEndpointsProtocol=https;AccountName=myaccount;...")
345
.containerName("mycontainer")
346
.buildAsyncClient();
347
```
348
349
### Async Container Operations
350
351
```java
352
// Create container asynchronously
353
Mono<Void> createMono = asyncContainerClient.create();
354
createMono
355
.doOnSuccess(v -> System.out.println("Container created successfully"))
356
.doOnError(ex -> System.err.println("Container creation failed: " + ex.getMessage()))
357
.subscribe();
358
359
// Chain operations
360
asyncContainerClient.createIfNotExists()
361
.filter(created -> created) // Only proceed if container was actually created
362
.flatMap(created -> {
363
Map<String, String> metadata = Map.of("created-time", OffsetDateTime.now().toString());
364
return asyncContainerClient.setMetadata(metadata);
365
})
366
.doOnSuccess(v -> System.out.println("Container created and metadata set"))
367
.subscribe();
368
369
// Get properties asynchronously
370
Mono<BlobContainerProperties> propertiesMono = asyncContainerClient.getProperties();
371
propertiesMono
372
.doOnNext(props -> {
373
System.out.println("Container last modified: " + props.getLastModified());
374
System.out.println("Public access: " + props.getPublicAccess());
375
System.out.println("Metadata count: " + props.getMetadata().size());
376
})
377
.subscribe();
378
```
379
380
### Async Blob Listing
381
382
```java
383
// List blobs asynchronously
384
Flux<BlobItem> blobFlux = asyncContainerClient.listBlobs();
385
386
blobFlux
387
.take(50) // Limit to first 50 blobs
388
.doOnNext(blob -> System.out.println("Blob: " + blob.getName() +
389
" (" + blob.getProperties().getContentLength() + " bytes)"))
390
.doOnComplete(() -> System.out.println("Listing complete"))
391
.doOnError(ex -> System.err.println("Listing failed: " + ex.getMessage()))
392
.subscribe();
393
394
// List with filtering
395
ListBlobsOptions listOptions = new ListBlobsOptions()
396
.setPrefix("images/")
397
.setMaxResultsPerPage(25);
398
399
Flux<BlobItem> filteredBlobFlux = asyncContainerClient.listBlobs(listOptions);
400
401
// Process blobs in parallel
402
filteredBlobFlux
403
.flatMap(blob -> {
404
BlobAsyncClient blobAsyncClient = asyncContainerClient.getBlobAsyncClient(blob.getName());
405
return blobAsyncClient.getProperties()
406
.map(props -> blob.getName() + " - " + props.getContentType());
407
}, 5) // Max 5 concurrent operations
408
.doOnNext(info -> System.out.println(info))
409
.subscribe();
410
```
411
412
### Error Handling with Async Container Client
413
414
```java
415
import com.azure.storage.blob.models.BlobStorageException;
416
417
// Comprehensive error handling
418
asyncContainerClient.create()
419
.doOnSuccess(v -> System.out.println("Container created"))
420
.onErrorResume(BlobStorageException.class, ex -> {
421
if (ex.getErrorCode() == BlobErrorCode.CONTAINER_ALREADY_EXISTS) {
422
System.out.println("Container already exists, continuing...");
423
return Mono.empty();
424
} else {
425
System.err.println("Storage error: " + ex.getErrorCode() + " - " + ex.getMessage());
426
return Mono.error(ex);
427
}
428
})
429
.onErrorResume(Exception.class, ex -> {
430
System.err.println("Unexpected error: " + ex.getMessage());
431
return Mono.error(new RuntimeException("Container creation failed", ex));
432
})
433
.subscribe();
434
435
// Retry operations
436
asyncContainerClient.getProperties()
437
.retry(3) // Retry up to 3 times on any error
438
.doOnNext(props -> System.out.println("Properties retrieved: " + props.getETag()))
439
.doOnError(ex -> System.err.println("Failed after retries: " + ex.getMessage()))
440
.subscribe();
441
```
442
443
## Container Leasing
444
445
### Lease Management
446
447
```java
448
import com.azure.storage.blob.specialized.BlobLeaseClient;
449
import com.azure.storage.blob.specialized.BlobLeaseClientBuilder;
450
451
// Create lease client for container
452
BlobLeaseClient leaseClient = new BlobLeaseClientBuilder()
453
.containerClient(containerClient)
454
.buildClient();
455
456
// Acquire lease
457
String proposedLeaseId = UUID.randomUUID().toString();
458
String leaseId = leaseClient.acquireLease(60); // 60 second lease
459
System.out.println("Acquired lease: " + leaseId);
460
461
try {
462
// Operations with lease
463
BlobRequestConditions leaseConditions = new BlobRequestConditions()
464
.setLeaseId(leaseId);
465
466
containerClient.setMetadataWithResponse(
467
Map.of("leased", "true"),
468
leaseConditions,
469
Duration.ofSeconds(30),
470
Context.NONE
471
);
472
473
// Renew lease
474
leaseClient.renewLease();
475
476
// Break lease (if needed)
477
Integer breakPeriod = leaseClient.breakLease();
478
System.out.println("Lease will be broken in " + breakPeriod + " seconds");
479
480
} finally {
481
// Always release lease
482
try {
483
leaseClient.releaseLease();
484
System.out.println("Lease released");
485
} catch (Exception ex) {
486
System.err.println("Failed to release lease: " + ex.getMessage());
487
}
488
}
489
```
490
491
## Container Properties
492
493
### Key Properties and Methods
494
495
```java
496
// Container identification
497
String containerName = containerClient.getBlobContainerName();
498
String accountName = containerClient.getAccountName();
499
String containerUrl = containerClient.getBlobContainerUrl();
500
501
System.out.println("Container: " + containerName);
502
System.out.println("Account: " + accountName);
503
System.out.println("URL: " + containerUrl);
504
505
// Service information
506
BlobServiceVersion serviceVersion = containerClient.getServiceVersion();
507
System.out.println("Service version: " + serviceVersion.getVersion());
508
509
// Get account info through container
510
StorageAccountInfo accountInfo = containerClient.getAccountInfo();
511
System.out.println("Account kind: " + accountInfo.getAccountKind());
512
System.out.println("SKU: " + accountInfo.getSkuName());
513
```
514
515
## Special Containers
516
517
### Working with System Containers
518
519
```java
520
// Root container ($root) - blobs accessible at account level
521
BlobContainerClient rootContainer = serviceClient.getBlobContainerClient(BlobContainerClient.ROOT_CONTAINER_NAME);
522
523
// Static website container ($web)
524
BlobContainerClient webContainer = serviceClient.getBlobContainerClient(BlobContainerClient.STATIC_WEBSITE_CONTAINER_NAME);
525
526
// Logs container ($logs) - for analytics logging
527
BlobContainerClient logsContainer = serviceClient.getBlobContainerClient(BlobContainerClient.LOG_CONTAINER_NAME);
528
529
// Check if system containers exist before using
530
if (rootContainer.exists()) {
531
System.out.println("Root container is available");
532
}
533
534
// Upload to root container (blob accessible at https://account.blob.core.windows.net/filename)
535
BlobClient rootBlob = rootContainer.getBlobClient("favicon.ico");
536
rootBlob.uploadFromFile("favicon.ico");
537
```
538
539
## Batch Operations
540
541
### Bulk Container Operations
542
543
```java
544
// Process multiple containers
545
List<String> containerNames = Arrays.asList("container1", "container2", "container3");
546
547
// Create multiple containers
548
containerNames.forEach(name -> {
549
try {
550
BlobContainerClient client = serviceClient.getBlobContainerClient(name);
551
client.createIfNotExists();
552
System.out.println("Ensured container exists: " + name);
553
} catch (Exception ex) {
554
System.err.println("Failed to create container " + name + ": " + ex.getMessage());
555
}
556
});
557
558
// Set metadata on multiple containers
559
Map<String, String> commonMetadata = Map.of(
560
"batch-operation", "true",
561
"timestamp", OffsetDateTime.now().toString()
562
);
563
564
containerNames.forEach(name -> {
565
try {
566
BlobContainerClient client = serviceClient.getBlobContainerClient(name);
567
if (client.exists()) {
568
client.setMetadata(commonMetadata);
569
System.out.println("Set metadata on: " + name);
570
}
571
} catch (Exception ex) {
572
System.err.println("Failed to set metadata on " + name + ": " + ex.getMessage());
573
}
574
});
575
```
576
577
## Related Documentation
578
579
- [← Back to Overview](index.md)
580
- [← Service Client Operations](service-client.md)
581
- [Blob Operations →](blob-client.md)
582
- [Security & Authentication →](security.md)
583
- [Configuration Options →](options.md)