or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

blob-client.mdcontainer-client.mdindex.mdmodels.mdoptions.mdsecurity.mdservice-client.mdspecialized-clients.mdstreaming.md

specialized-clients.mddocs/

0

# Specialized Blob Clients

1

2

Azure Blob Storage supports three specialized blob types, each optimized for different use cases. This documentation covers BlockBlobClient, AppendBlobClient, and PageBlobClient for both synchronous and asynchronous operations.

3

4

## Block Blobs - BlockBlobClient

5

6

Block blobs are optimized for uploading large amounts of data efficiently and are ideal for streaming scenarios.

7

8

### Creating Block Blob Clients

9

10

```java

11

import com.azure.storage.blob.specialized.BlockBlobClient;

12

import com.azure.storage.blob.specialized.BlockBlobAsyncClient;

13

import com.azure.storage.blob.specialized.SpecializedBlobClientBuilder;

14

15

// From base blob client (recommended)

16

BlobClient blobClient = containerClient.getBlobClient("document.pdf");

17

BlockBlobClient blockBlobClient = blobClient.getBlockBlobClient();

18

19

// Using specialized builder

20

BlockBlobClient blockBlobClient = new SpecializedBlobClientBuilder()

21

.blobClient(blobClient)

22

.buildBlockBlobClient();

23

24

// Async version

25

BlockBlobAsyncClient asyncBlockBlobClient = new SpecializedBlobClientBuilder()

26

.blobAsyncClient(blobAsyncClient)

27

.buildBlockBlobAsyncClient();

28

```

29

30

### Block Blob Upload Operations

31

32

```java

33

import com.azure.storage.blob.models.*;

34

import com.azure.core.util.BinaryData;

35

36

// Simple upload (entire blob in one operation)

37

String content = "Complete document content for block blob";

38

BlockBlobItem uploadResult = blockBlobClient.upload(

39

BinaryData.fromString(content),

40

true // overwrite if exists

41

);

42

43

System.out.println("Block blob uploaded: " + uploadResult.getETag());

44

System.out.println("Content MD5: " + Arrays.toString(uploadResult.getContentMd5()));

45

System.out.println("Version ID: " + uploadResult.getVersionId());

46

47

// Upload with comprehensive options

48

BlobHttpHeaders headers = new BlobHttpHeaders()

49

.setContentType("application/pdf")

50

.setContentDisposition("attachment; filename=document.pdf")

51

.setCacheControl("public, max-age=31536000");

52

53

Map<String, String> metadata = Map.of(

54

"document-type", "invoice",

55

"department", "accounting",

56

"year", "2023"

57

);

58

59

BlobRequestConditions conditions = new BlobRequestConditions()

60

.setIfNoneMatch("*"); // Only upload if blob doesn't exist

61

62

Response<BlockBlobItem> uploadResponse = blockBlobClient.uploadWithResponse(

63

BinaryData.fromString(content),

64

content.length(),

65

headers,

66

metadata,

67

AccessTier.HOT,

68

null, // contentMd5

69

conditions,

70

Duration.ofMinutes(10),

71

Context.NONE

72

);

73

74

System.out.println("Upload status: " + uploadResponse.getStatusCode());

75

```

76

77

### Upload from URL

78

79

```java

80

// Upload from another URL (server-side copy)

81

String sourceUrl = "https://example.com/source-file.pdf";

82

83

BlockBlobItem urlUploadResult = blockBlobClient.uploadFromUrl(sourceUrl);

84

System.out.println("Upload from URL completed: " + urlUploadResult.getETag());

85

86

// Upload from URL with options

87

BlobUploadFromUrlOptions urlOptions = new BlobUploadFromUrlOptions(sourceUrl)

88

.setHeaders(new BlobHttpHeaders().setContentType("application/pdf"))

89

.setMetadata(Map.of("source", "external"))

90

.setTags(Map.of("imported", "true"))

91

.setTier(AccessTier.HOT)

92

.setRequestConditions(new BlobRequestConditions().setIfNoneMatch("*"))

93

.setSourceRequestConditions(new BlobRequestConditions()

94

.setIfModifiedSince(OffsetDateTime.now().minusDays(1)));

95

96

Response<BlockBlobItem> urlUploadResponse = blockBlobClient.uploadFromUrlWithResponse(

97

urlOptions,

98

Duration.ofMinutes(5),

99

Context.NONE

100

);

101

```

102

103

### Block-Level Operations

104

105

```java

106

import java.util.Base64;

107

import java.util.List;

108

import java.util.ArrayList;

109

110

// Stage individual blocks (for large file uploads)

111

List<String> blockIds = new ArrayList<>();

112

113

// Block 1

114

String blockId1 = Base64.getEncoder().encodeToString("block-001".getBytes());

115

byte[] blockData1 = "First part of the content".getBytes();

116

blockBlobClient.stageBlock(blockId1, BinaryData.fromBytes(blockData1));

117

blockIds.add(blockId1);

118

119

// Block 2

120

String blockId2 = Base64.getEncoder().encodeToString("block-002".getBytes());

121

byte[] blockData2 = "Second part of the content".getBytes();

122

blockBlobClient.stageBlock(blockId2, BinaryData.fromBytes(blockData2));

123

blockIds.add(blockId2);

124

125

// Stage block with options

126

String blockId3 = Base64.getEncoder().encodeToString("block-003".getBytes());

127

byte[] blockData3 = "Third part with checksum".getBytes();

128

byte[] blockMd5 = MessageDigest.getInstance("MD5").digest(blockData3);

129

130

Response<Void> stageResponse = blockBlobClient.stageBlockWithResponse(

131

blockId3,

132

BinaryData.fromBytes(blockData3),

133

blockMd5,

134

null, // leaseId

135

Duration.ofMinutes(2),

136

Context.NONE

137

);

138

blockIds.add(blockId3);

139

140

// Commit all blocks to create the final blob

141

BlockBlobItem commitResult = blockBlobClient.commitBlockList(blockIds);

142

System.out.println("Blocks committed: " + commitResult.getETag());

143

144

// Commit with additional options

145

Response<BlockBlobItem> commitResponse = blockBlobClient.commitBlockListWithResponse(

146

blockIds,

147

new BlobHttpHeaders().setContentType("text/plain"),

148

Map.of("blocks-count", String.valueOf(blockIds.size())),

149

AccessTier.HOT,

150

new BlobRequestConditions().setIfNoneMatch("*"),

151

Duration.ofMinutes(5),

152

Context.NONE

153

);

154

```

155

156

### Block Management

157

158

```java

159

// List current blocks

160

BlockList blockList = blockBlobClient.listBlocks(BlockListType.ALL);

161

162

System.out.println("Committed blocks:");

163

for (Block block : blockList.getCommittedBlocks()) {

164

System.out.println(" Block ID: " + block.getName());

165

System.out.println(" Size: " + block.getSizeLong() + " bytes");

166

}

167

168

System.out.println("Uncommitted blocks:");

169

for (Block block : blockList.getUncommittedBlocks()) {

170

System.out.println(" Block ID: " + block.getName());

171

System.out.println(" Size: " + block.getSizeLong() + " bytes");

172

}

173

174

// List blocks with lease ID

175

String leaseId = acquiredLeaseId; // From lease operations

176

Response<BlockList> blockListResponse = blockBlobClient.listBlocksWithResponse(

177

BlockListType.COMMITTED,

178

leaseId,

179

Duration.ofSeconds(30),

180

Context.NONE

181

);

182

183

// Stage block from URL

184

String sourceBlockUrl = "https://source.blob.core.windows.net/container/source.txt";

185

BlobRange sourceRange = new BlobRange(0, 1024L); // First 1KB

186

187

blockBlobClient.stageBlockFromUrl(blockId1, sourceBlockUrl, sourceRange);

188

189

// Stage block from URL with options

190

BlockBlobStageBlockFromUrlOptions stageFromUrlOptions = new BlockBlobStageBlockFromUrlOptions(

191

blockId2, sourceBlockUrl)

192

.setSourceRange(new BlobRange(1024, 1024L)) // Next 1KB

193

.setSourceContentMd5(sourceMd5Hash)

194

.setLeaseId(leaseId)

195

.setSourceRequestConditions(new BlobRequestConditions()

196

.setIfMatch(sourceETag));

197

198

Response<Void> stageFromUrlResponse = blockBlobClient.stageBlockFromUrlWithResponse(

199

stageFromUrlOptions,

200

Duration.ofMinutes(2),

201

Context.NONE

202

);

203

```

204

205

### Block Blob Streaming

206

207

```java

208

// Get output stream for writing

209

BlobOutputStream blobOutputStream = blockBlobClient.getBlobOutputStream();

210

211

try (blobOutputStream) {

212

// Write data in chunks

213

blobOutputStream.write("First chunk of data\n".getBytes());

214

blobOutputStream.write("Second chunk of data\n".getBytes());

215

blobOutputStream.write("Final chunk of data\n".getBytes());

216

217

// Stream automatically commits blocks when closed

218

} catch (IOException ex) {

219

System.err.println("Stream write failed: " + ex.getMessage());

220

}

221

222

// Get output stream with options

223

ParallelTransferOptions streamTransferOptions = new ParallelTransferOptions()

224

.setBlockSizeLong(2 * 1024 * 1024L) // 2MB blocks

225

.setMaxConcurrency(4);

226

227

BlobHttpHeaders streamHeaders = new BlobHttpHeaders()

228

.setContentType("text/plain")

229

.setContentEncoding("utf-8");

230

231

Map<String, String> streamMetadata = Map.of(

232

"streaming", "true",

233

"created", OffsetDateTime.now().toString()

234

);

235

236

BlobOutputStream configuredStream = blockBlobClient.getBlobOutputStream(

237

streamTransferOptions,

238

streamHeaders,

239

streamMetadata,

240

AccessTier.HOT,

241

new BlobRequestConditions().setIfNoneMatch("*"),

242

Context.NONE

243

);

244

245

try (configuredStream) {

246

// Write large amounts of data

247

for (int i = 0; i < 1000; i++) {

248

configuredStream.write(("Line " + i + " of streaming data\n").getBytes());

249

}

250

}

251

```

252

253

## Append Blobs - AppendBlobClient

254

255

Append blobs are optimized for append operations and are ideal for logging scenarios.

256

257

### Creating Append Blob Clients

258

259

```java

260

import com.azure.storage.blob.specialized.AppendBlobClient;

261

import com.azure.storage.blob.specialized.AppendBlobAsyncClient;

262

263

// From base blob client

264

AppendBlobClient appendBlobClient = blobClient.getAppendBlobClient();

265

266

// Using specialized builder

267

AppendBlobClient appendBlobClient = new SpecializedBlobClientBuilder()

268

.blobClient(blobClient)

269

.buildAppendBlobClient();

270

271

// Async version

272

AppendBlobAsyncClient asyncAppendBlobClient = new SpecializedBlobClientBuilder()

273

.blobAsyncClient(blobAsyncClient)

274

.buildAppendBlobAsyncClient();

275

```

276

277

### Append Blob Lifecycle

278

279

```java

280

// Create append blob

281

AppendBlobItem createResult = appendBlobClient.create();

282

System.out.println("Append blob created: " + createResult.getETag());

283

284

// Create with options

285

BlobHttpHeaders appendHeaders = new BlobHttpHeaders()

286

.setContentType("text/plain")

287

.setContentEncoding("utf-8");

288

289

Map<String, String> appendMetadata = Map.of(

290

"log-type", "application",

291

"service", "web-api",

292

"environment", "production"

293

);

294

295

Response<AppendBlobItem> createResponse = appendBlobClient.createWithResponse(

296

appendHeaders,

297

appendMetadata,

298

new BlobRequestConditions().setIfNoneMatch("*"),

299

Duration.ofSeconds(30),

300

Context.NONE

301

);

302

303

// Create if not exists

304

AppendBlobItem createIfNotExistsResult = appendBlobClient.createIfNotExists();

305

if (createIfNotExistsResult != null) {

306

System.out.println("New append blob created");

307

} else {

308

System.out.println("Append blob already exists");

309

}

310

311

// Create if not exists with options

312

AppendBlobCreateOptions createOptions = new AppendBlobCreateOptions()

313

.setHeaders(appendHeaders)

314

.setMetadata(appendMetadata);

315

316

Response<AppendBlobItem> createIfNotExistsResponse = appendBlobClient.createIfNotExistsWithResponse(

317

createOptions,

318

Duration.ofSeconds(30),

319

Context.NONE

320

);

321

```

322

323

### Append Operations

324

325

```java

326

// Simple append operation

327

String logEntry = "[" + OffsetDateTime.now() + "] INFO: User logged in\n";

328

AppendBlobItem appendResult = appendBlobClient.appendBlock(BinaryData.fromString(logEntry));

329

330

System.out.println("Append completed: " + appendResult.getBlobAppendOffset());

331

System.out.println("Blob committed block count: " + appendResult.getBlobCommittedBlockCount());

332

333

// Append with conditions

334

AppendBlobRequestConditions appendConditions = new AppendBlobRequestConditions()

335

.setIfMatch(appendResult.getETag())

336

.setAppendPositionEqual(appendResult.getBlobAppendOffset() + logEntry.getBytes().length);

337

338

String nextLogEntry = "[" + OffsetDateTime.now() + "] WARN: High memory usage\n";

339

byte[] logBytes = nextLogEntry.getBytes(StandardCharsets.UTF_8);

340

byte[] logMd5 = MessageDigest.getInstance("MD5").digest(logBytes);

341

342

Response<AppendBlobItem> appendResponse = appendBlobClient.appendBlockWithResponse(

343

BinaryData.fromBytes(logBytes),

344

logMd5,

345

appendConditions,

346

Duration.ofSeconds(30),

347

Context.NONE

348

);

349

350

// Append from URL

351

String sourceLogUrl = "https://source.blob.core.windows.net/logs/app.log";

352

BlobRange sourceRange = new BlobRange(0, 1024L); // First 1KB

353

354

AppendBlobItem urlAppendResult = appendBlobClient.appendBlockFromUrl(sourceLogUrl, sourceRange);

355

356

// Append from URL with options

357

AppendBlobAppendBlockFromUrlOptions urlAppendOptions = new AppendBlobAppendBlockFromUrlOptions(

358

sourceLogUrl, sourceRange)

359

.setSourceContentMd5(sourceMd5)

360

.setDestinationRequestConditions(new AppendBlobRequestConditions()

361

.setMaxSize(100 * 1024 * 1024L)) // Max 100MB

362

.setSourceRequestConditions(new BlobRequestConditions()

363

.setIfUnmodifiedSince(OffsetDateTime.now()));

364

365

Response<AppendBlobItem> urlAppendResponse = appendBlobClient.appendBlockFromUrlWithResponse(

366

urlAppendOptions,

367

Duration.ofMinutes(2),

368

Context.NONE

369

);

370

```

371

372

### Append Blob Sealing

373

374

```java

375

// Seal append blob (make it read-only)

376

appendBlobClient.seal();

377

System.out.println("Append blob sealed - no more appends allowed");

378

379

// Seal with conditions

380

AppendBlobSealOptions sealOptions = new AppendBlobSealOptions()

381

.setRequestConditions(new AppendBlobRequestConditions()

382

.setIfMatch(currentETag)

383

.setLeaseId(leaseId));

384

385

Response<Void> sealResponse = appendBlobClient.sealWithResponse(

386

sealOptions,

387

Duration.ofSeconds(30),

388

Context.NONE

389

);

390

391

System.out.println("Seal operation status: " + sealResponse.getStatusCode());

392

393

// Check if blob is sealed

394

BlobProperties properties = appendBlobClient.getProperties();

395

if (properties.isSealed()) {

396

System.out.println("Blob is sealed");

397

} else {

398

System.out.println("Blob is not sealed");

399

}

400

```

401

402

### Logging Pattern with Append Blobs

403

404

```java

405

// Complete logging example

406

public class BlobLogger {

407

private final AppendBlobClient logBlobClient;

408

private final String logFormat = "[%s] %s: %s%n";

409

410

public BlobLogger(BlobContainerClient containerClient, String logFileName) {

411

this.logBlobClient = containerClient.getBlobClient(logFileName).getAppendBlobClient();

412

413

// Ensure log file exists

414

try {

415

logBlobClient.createIfNotExists();

416

} catch (Exception ex) {

417

throw new RuntimeException("Failed to initialize log file", ex);

418

}

419

}

420

421

public void log(String level, String message) {

422

String logEntry = String.format(logFormat,

423

OffsetDateTime.now(), level, message);

424

425

try {

426

AppendBlobItem result = logBlobClient.appendBlock(BinaryData.fromString(logEntry));

427

System.out.println("Log written at offset: " + result.getBlobAppendOffset());

428

} catch (Exception ex) {

429

System.err.println("Failed to write log: " + ex.getMessage());

430

}

431

}

432

433

public void info(String message) { log("INFO", message); }

434

public void warn(String message) { log("WARN", message); }

435

public void error(String message) { log("ERROR", message); }

436

}

437

438

// Usage

439

BlobLogger logger = new BlobLogger(containerClient, "application.log");

440

logger.info("Application started");

441

logger.warn("High memory usage detected");

442

logger.error("Database connection failed");

443

```

444

445

## Page Blobs - PageBlobClient

446

447

Page blobs provide random read/write access and are ideal for VHD files and database scenarios.

448

449

### Creating Page Blob Clients

450

451

```java

452

import com.azure.storage.blob.specialized.PageBlobClient;

453

import com.azure.storage.blob.specialized.PageBlobAsyncClient;

454

455

// From base blob client

456

PageBlobClient pageBlobClient = blobClient.getPageBlobClient();

457

458

// Using specialized builder

459

PageBlobClient pageBlobClient = new SpecializedBlobClientBuilder()

460

.blobClient(blobClient)

461

.buildPageBlobClient();

462

463

// Async version

464

PageBlobAsyncClient asyncPageBlobClient = new SpecializedBlobClientBuilder()

465

.blobAsyncClient(blobAsyncClient)

466

.buildPageBlobAsyncClient();

467

```

468

469

### Page Blob Creation and Sizing

470

471

```java

472

// Create page blob with specific size (must be multiple of 512 bytes)

473

long pageBlobSize = 1024 * 1024 * 512L; // 512MB

474

PageBlobItem createResult = pageBlobClient.create(pageBlobSize);

475

476

System.out.println("Page blob created: " + createResult.getETag());

477

System.out.println("Sequence number: " + createResult.getBlobSequenceNumber());

478

479

// Create with options

480

BlobHttpHeaders pageHeaders = new BlobHttpHeaders()

481

.setContentType("application/octet-stream");

482

483

Map<String, String> pageMetadata = Map.of(

484

"type", "vhd",

485

"vm-name", "web-server-01",

486

"size-mb", String.valueOf(pageBlobSize / (1024 * 1024))

487

);

488

489

Long sequenceNumber = 0L;

490

491

Response<PageBlobItem> createResponse = pageBlobClient.createWithResponse(

492

pageBlobSize,

493

sequenceNumber,

494

pageHeaders,

495

pageMetadata,

496

AccessTier.PREMIUM,

497

new BlobRequestConditions().setIfNoneMatch("*"),

498

Duration.ofMinutes(2),

499

Context.NONE

500

);

501

502

// Create if not exists

503

PageBlobItem createIfNotExistsResult = pageBlobClient.createIfNotExists(pageBlobSize);

504

if (createIfNotExistsResult != null) {

505

System.out.println("New page blob created");

506

} else {

507

System.out.println("Page blob already exists");

508

}

509

510

// Create if not exists with options

511

PageBlobCreateOptions createOptions = new PageBlobCreateOptions(pageBlobSize)

512

.setSequenceNumber(0L)

513

.setHeaders(pageHeaders)

514

.setMetadata(pageMetadata)

515

.setTier(AccessTier.PREMIUM);

516

517

Response<PageBlobItem> createIfNotExistsResponse = pageBlobClient.createIfNotExistsWithResponse(

518

createOptions,

519

Duration.ofMinutes(2),

520

Context.NONE

521

);

522

```

523

524

### Page Operations

525

526

```java

527

import com.azure.storage.blob.models.PageRange;

528

529

// Upload pages (must be 512-byte aligned)

530

PageRange pageRange1 = new PageRange().setStart(0).setEnd(511); // First page (512 bytes)

531

byte[] pageData1 = new byte[512];

532

Arrays.fill(pageData1, (byte) 0xAA); // Fill with pattern

533

534

PageBlobItem uploadResult = pageBlobClient.uploadPages(pageRange1, BinaryData.fromBytes(pageData1));

535

System.out.println("Page uploaded: " + uploadResult.getETag());

536

537

// Upload multiple pages

538

PageRange pageRange2 = new PageRange().setStart(512).setEnd(1023); // Second page

539

byte[] pageData2 = new byte[512];

540

Arrays.fill(pageData2, (byte) 0xBB);

541

542

byte[] pageMd5 = MessageDigest.getInstance("MD5").digest(pageData2);

543

PageBlobRequestConditions pageConditions = new PageBlobRequestConditions()

544

.setIfSequenceNumberEqual(uploadResult.getBlobSequenceNumber());

545

546

Response<PageBlobItem> uploadResponse = pageBlobClient.uploadPagesWithResponse(

547

pageRange2,

548

BinaryData.fromBytes(pageData2),

549

pageMd5,

550

pageConditions,

551

Duration.ofMinutes(2),

552

Context.NONE

553

);

554

555

// Upload pages from URL

556

String sourcePageUrl = "https://source.blob.core.windows.net/vhds/template.vhd";

557

Long sourceOffset = 0L;

558

559

PageBlobItem urlUploadResult = pageBlobClient.uploadPagesFromUrl(

560

pageRange1,

561

sourcePageUrl,

562

sourceOffset

563

);

564

565

// Upload pages from URL with options

566

PageBlobUploadPagesFromUrlOptions urlUploadOptions = new PageBlobUploadPagesFromUrlOptions(

567

pageRange2, sourcePageUrl, sourceOffset + 512L)

568

.setSourceContentMd5(sourceMd5)

569

.setDestinationRequestConditions(new PageBlobRequestConditions()

570

.setIfMatch(uploadResult.getETag()))

571

.setSourceRequestConditions(new BlobRequestConditions()

572

.setIfUnmodifiedSince(OffsetDateTime.now()));

573

574

Response<PageBlobItem> urlUploadResponse = pageBlobClient.uploadPagesFromUrlWithResponse(

575

urlUploadOptions,

576

Duration.ofMinutes(5),

577

Context.NONE

578

);

579

```

580

581

### Page Management

582

583

```java

584

// Get page ranges (find which pages contain data)

585

PageList pageList = pageBlobClient.getPageRanges(new BlobRange(0, 2048L));

586

587

System.out.println("Page ranges with data:");

588

for (PageRange range : pageList.getPageRanges()) {

589

System.out.println(" Pages " + range.getStart() + " to " + range.getEnd());

590

}

591

592

System.out.println("Clear page ranges:");

593

for (PageRange range : pageList.getClearRanges()) {

594

System.out.println(" Clear pages " + range.getStart() + " to " + range.getEnd());

595

}

596

597

// Get page ranges with conditions

598

Response<PageList> pageListResponse = pageBlobClient.getPageRangesWithResponse(

599

new BlobRange(0),

600

new BlobRequestConditions().setIfMatch(currentETag),

601

Duration.ofSeconds(30),

602

Context.NONE

603

);

604

605

// Clear pages (deallocate storage)

606

PageRange clearRange = new PageRange().setStart(1024).setEnd(1535); // Third page

607

PageBlobItem clearResult = pageBlobClient.clearPages(clearRange);

608

System.out.println("Pages cleared: " + clearResult.getETag());

609

610

// Clear pages with conditions

611

Response<PageBlobItem> clearResponse = pageBlobClient.clearPagesWithResponse(

612

clearRange,

613

new PageBlobRequestConditions().setIfSequenceNumberLessThan(100L),

614

Duration.ofSeconds(30),

615

Context.NONE

616

);

617

618

// Get page ranges diff (compare with snapshot)

619

String previousSnapshot = "2023-12-01T10:30:00.0000000Z";

620

PageList pageRangesDiff = pageBlobClient.getPageRangesDiff(

621

new BlobRange(0),

622

previousSnapshot

623

);

624

625

System.out.println("Pages modified since snapshot:");

626

for (PageRange modifiedRange : pageRangesDiff.getPageRanges()) {

627

System.out.println(" Modified: " + modifiedRange.getStart() + " to " + modifiedRange.getEnd());

628

}

629

```

630

631

### Page Blob Resizing

632

633

```java

634

// Resize page blob

635

long newSize = 2 * 1024 * 1024 * 512L; // 1GB

636

PageBlobItem resizeResult = pageBlobClient.resize(newSize);

637

System.out.println("Blob resized: " + resizeResult.getETag());

638

639

// Resize with conditions

640

Response<PageBlobItem> resizeResponse = pageBlobClient.resizeWithResponse(

641

newSize,

642

new BlobRequestConditions().setIfUnmodifiedSince(OffsetDateTime.now()),

643

Duration.ofMinutes(2),

644

Context.NONE

645

);

646

647

// Get current size

648

BlobProperties properties = pageBlobClient.getProperties();

649

System.out.println("Current size: " + properties.getBlobSize() + " bytes");

650

System.out.println("Current sequence number: " + properties.getBlobSequenceNumber());

651

```

652

653

### Sequence Number Management

654

655

```java

656

import com.azure.storage.blob.models.SequenceNumberActionType;

657

658

// Update sequence number (for optimistic concurrency control)

659

Long newSequenceNumber = 42L;

660

661

// Set to specific value

662

PageBlobItem updateResult = pageBlobClient.updateSequenceNumber(

663

SequenceNumberActionType.UPDATE,

664

newSequenceNumber

665

);

666

667

// Increment by 1

668

PageBlobItem incrementResult = pageBlobClient.updateSequenceNumber(

669

SequenceNumberActionType.INCREMENT,

670

null // ignored for increment

671

);

672

673

// Set to maximum of current and provided value

674

PageBlobItem maxResult = pageBlobClient.updateSequenceNumber(

675

SequenceNumberActionType.MAX,

676

newSequenceNumber

677

);

678

679

System.out.println("New sequence number: " + updateResult.getBlobSequenceNumber());

680

681

// Update with conditions

682

Response<PageBlobItem> updateResponse = pageBlobClient.updateSequenceNumberWithResponse(

683

SequenceNumberActionType.UPDATE,

684

100L,

685

new BlobRequestConditions().setIfSequenceNumberEqual(incrementResult.getBlobSequenceNumber()),

686

Duration.ofSeconds(30),

687

Context.NONE

688

);

689

```

690

691

### Incremental Copy (Page Blob Snapshots)

692

693

```java

694

// Perform incremental copy (copy only changed pages)

695

String sourcePageBlobUrl = "https://source.blob.core.windows.net/vhds/base.vhd";

696

String sourceSnapshot = "2023-12-01T10:30:00.0000000Z";

697

698

CopyStatusType copyStatus = pageBlobClient.copyIncremental(sourcePageBlobUrl, sourceSnapshot);

699

System.out.println("Incremental copy status: " + copyStatus);

700

701

// Incremental copy with options

702

PageBlobCopyIncrementalOptions copyOptions = new PageBlobCopyIncrementalOptions(

703

sourcePageBlobUrl, sourceSnapshot)

704

.setRequestConditions(new BlobRequestConditions()

705

.setIfNoneMatch("*"));

706

707

Response<CopyStatusType> copyResponse = pageBlobClient.copyIncrementalWithResponse(

708

copyOptions,

709

Duration.ofMinutes(10),

710

Context.NONE

711

);

712

713

// Monitor copy progress

714

BlobProperties copyProperties = pageBlobClient.getProperties();

715

while (copyProperties.getCopyStatus() == CopyStatusType.PENDING) {

716

System.out.println("Copy progress: " + copyProperties.getCopyProgress());

717

Thread.sleep(5000); // Wait 5 seconds

718

copyProperties = pageBlobClient.getProperties();

719

}

720

721

System.out.println("Final copy status: " + copyProperties.getCopyStatus());

722

```

723

724

## Async Specialized Clients

725

726

### Async Block Blob Operations

727

728

```java

729

import reactor.core.publisher.Mono;

730

import reactor.core.publisher.Flux;

731

732

// Async block blob operations

733

BlockBlobAsyncClient asyncBlockBlobClient = asyncBlobClient.getBlockBlobAsyncClient();

734

735

// Async upload

736

Mono<BlockBlobItem> uploadMono = asyncBlockBlobClient.upload(

737

BinaryData.fromString("Async block blob content"),

738

true

739

);

740

741

uploadMono

742

.doOnSuccess(result -> System.out.println("Async upload: " + result.getETag()))

743

.doOnError(ex -> System.err.println("Upload failed: " + ex.getMessage()))

744

.subscribe();

745

746

// Async block staging and committing

747

List<String> blockIds = new ArrayList<>();

748

String blockId = Base64.getEncoder().encodeToString("async-block".getBytes());

749

750

Mono<Void> stageBlockMono = asyncBlockBlobClient.stageBlock(blockId, BinaryData.fromString("Block content"));

751

Mono<BlockBlobItem> commitMono = stageBlockMono.then(

752

asyncBlockBlobClient.commitBlockList(List.of(blockId))

753

);

754

755

commitMono

756

.doOnSuccess(result -> System.out.println("Async blocks committed: " + result.getETag()))

757

.subscribe();

758

```

759

760

### Async Append Blob Operations

761

762

```java

763

// Async append blob operations

764

AppendBlobAsyncClient asyncAppendBlobClient = asyncBlobClient.getAppendBlobAsyncClient();

765

766

// Create and append in sequence

767

Mono<Void> appendSequence = asyncAppendBlobClient.createIfNotExists()

768

.then(asyncAppendBlobClient.appendBlock(BinaryData.fromString("First log entry\n")))

769

.then(asyncAppendBlobClient.appendBlock(BinaryData.fromString("Second log entry\n")))

770

.then(asyncAppendBlobClient.appendBlock(BinaryData.fromString("Third log entry\n")))

771

.then();

772

773

appendSequence

774

.doOnSuccess(v -> System.out.println("Async append sequence completed"))

775

.doOnError(ex -> System.err.println("Append sequence failed: " + ex.getMessage()))

776

.subscribe();

777

778

// Reactive logging pattern

779

Flux<String> logMessages = Flux.just(

780

"Application started",

781

"User authenticated",

782

"Data processed",

783

"Application shutdown"

784

);

785

786

logMessages

787

.map(msg -> "[" + OffsetDateTime.now() + "] " + msg + "\n")

788

.map(BinaryData::fromString)

789

.flatMap(data -> asyncAppendBlobClient.appendBlock(data))

790

.doOnNext(result -> System.out.println("Log appended at: " + result.getBlobAppendOffset()))

791

.doOnComplete(() -> System.out.println("All log messages written"))

792

.subscribe();

793

```

794

795

### Async Page Blob Operations

796

797

```java

798

// Async page blob operations

799

PageBlobAsyncClient asyncPageBlobClient = asyncBlobClient.getPageBlobAsyncClient();

800

801

// Create and upload pages

802

long pageSize = 1024 * 512L; // 512KB

803

PageRange range = new PageRange().setStart(0).setEnd(511);

804

byte[] pageData = new byte[512];

805

806

Mono<Void> pageSequence = asyncPageBlobClient.create(pageSize)

807

.then(asyncPageBlobClient.uploadPages(range, BinaryData.fromBytes(pageData)))

808

.then();

809

810

pageSequence

811

.doOnSuccess(v -> System.out.println("Async page blob created and page uploaded"))

812

.doOnError(ex -> System.err.println("Page operation failed: " + ex.getMessage()))

813

.subscribe();

814

815

// Parallel page uploads

816

List<Mono<PageBlobItem>> pageUploads = new ArrayList<>();

817

for (int i = 0; i < 10; i++) {

818

PageRange pageRange = new PageRange()

819

.setStart(i * 512L)

820

.setEnd((i + 1) * 512L - 1);

821

byte[] data = new byte[512];

822

Arrays.fill(data, (byte) i);

823

824

pageUploads.add(asyncPageBlobClient.uploadPages(pageRange, BinaryData.fromBytes(data)));

825

}

826

827

Mono<Void> allPagesUploaded = Mono.when(pageUploads);

828

allPagesUploaded

829

.doOnSuccess(v -> System.out.println("All pages uploaded in parallel"))

830

.subscribe();

831

```

832

833

## Performance Considerations

834

835

### Optimal Block Sizes

836

837

```java

838

// Optimize block sizes based on file size and network conditions

839

public ParallelTransferOptions getOptimalTransferOptions(long fileSize) {

840

ParallelTransferOptions options = new ParallelTransferOptions();

841

842

if (fileSize < 32 * 1024 * 1024) { // < 32MB

843

options.setBlockSizeLong(1 * 1024 * 1024L); // 1MB blocks

844

options.setMaxConcurrency(4);

845

} else if (fileSize < 512 * 1024 * 1024) { // < 512MB

846

options.setBlockSizeLong(4 * 1024 * 1024L); // 4MB blocks

847

options.setMaxConcurrency(8);

848

} else { // >= 512MB

849

options.setBlockSizeLong(8 * 1024 * 1024L); // 8MB blocks

850

options.setMaxConcurrency(16);

851

}

852

853

return options;

854

}

855

856

// Usage for large file uploads

857

long fileSize = Files.size(Paths.get("largefile.dat"));

858

ParallelTransferOptions optimizedOptions = getOptimalTransferOptions(fileSize);

859

860

BlobUploadFromFileOptions uploadOptions = new BlobUploadFromFileOptions("largefile.dat")

861

.setParallelTransferOptions(optimizedOptions);

862

863

blockBlobClient.uploadFromFileWithResponse(uploadOptions, Duration.ofMinutes(30), Context.NONE);

864

```

865

866

## Related Documentation

867

868

- [← Back to Overview](index.md)

869

- [← Blob Operations](blob-client.md)

870

- [Streaming & Advanced I/O →](streaming.md)

871

- [Model Classes & Enums →](models.md)

872

- [Configuration Options →](options.md)