or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-clients.mddirectory-client.mdfile-client.mdindex.mdlease-client.mdmodels.mdsas-generation.mdservice-client.mdshare-client.md

file-client.mddocs/

0

# ShareFileClient - File Operations

1

2

The ShareFileClient provides comprehensive file management operations including upload/download, copying, range operations, metadata management, and advanced features like leasing and symbolic links.

3

4

## Import and Initialization

5

6

```python { .api }

7

from azure.storage.fileshare import ShareFileClient, ShareLeaseClient, ContentSettings

8

from azure.storage.fileshare import StorageStreamDownloader, Handle

9

from azure.core.credentials import AzureNamedKeyCredential

10

from typing import Optional, Union, Dict, Any, List, IO, AnyStr, Iterable, Tuple

11

```

12

13

## Constructor

14

15

```python { .api }

16

class ShareFileClient:

17

def __init__(

18

self,

19

account_url: str,

20

share_name: str,

21

file_path: str,

22

snapshot: Optional[Union[Dict[str, Any], str]] = None,

23

credential: Optional[Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, TokenCredential]] = None,

24

*,

25

token_intent: Optional[Literal['backup']] = None,

26

**kwargs: Any

27

) -> None:

28

"""

29

Create a ShareFileClient for a specific file.

30

31

Parameters:

32

account_url: The URL to the file service endpoint

33

share_name: Name of the share containing the file

34

file_path: Path to the file from share root

35

snapshot: Optional share snapshot identifier

36

credential: Authentication credential

37

token_intent: Specifies the intent for all requests when using TokenCredential authentication

38

**kwargs: Additional client configuration options

39

"""

40

```

41

42

## Class Methods

43

44

```python { .api }

45

@classmethod

46

def from_file_url(

47

cls,

48

file_url: str,

49

snapshot: Optional[Union[str, Dict[str, Any]]] = None,

50

credential: Optional[Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, TokenCredential]] = None,

51

**kwargs: Any

52

) -> ShareFileClient:

53

"""

54

Create ShareFileClient from file URL.

55

56

Parameters:

57

file_url: Complete URL to the file

58

snapshot: Optional share snapshot identifier

59

credential: Authentication credential

60

**kwargs: Additional client configuration options

61

62

Returns:

63

ShareFileClient: Configured client instance

64

"""

65

66

@classmethod

67

def from_connection_string(

68

cls,

69

conn_str: str,

70

share_name: str,

71

file_path: str,

72

snapshot: Optional[Union[str, Dict[str, Any]]] = None,

73

credential: Optional[Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, TokenCredential]] = None,

74

**kwargs: Any

75

) -> ShareFileClient:

76

"""

77

Create ShareFileClient from connection string.

78

79

Parameters:

80

conn_str: Azure Storage connection string

81

share_name: Name of the share

82

file_path: Path to the file from share root

83

snapshot: Optional share snapshot identifier

84

credential: Optional credential to override connection string auth

85

**kwargs: Additional client configuration options

86

87

Returns:

88

ShareFileClient: Configured client instance

89

"""

90

```

91

92

## File Lifecycle Operations

93

94

```python { .api }

95

def exists(

96

self,

97

**kwargs: Any

98

) -> bool:

99

"""

100

Returns True if the file exists, False otherwise.

101

102

Parameters:

103

timeout: Request timeout in seconds

104

105

Returns:

106

bool: True if file exists

107

"""

108

109

def create_file(

110

self,

111

size: int,

112

**kwargs: Any

113

) -> Dict[str, Any]:

114

"""

115

Creates a new file with the specified size.

116

117

Parameters:

118

size: Size of the file in bytes

119

content_settings: ContentSettings object with HTTP properties

120

metadata: Dict of name-value pairs for file metadata

121

file_attributes: File attributes (NTFSAttributes)

122

file_creation_time: Creation time for the file

123

file_last_write_time: Last write time for the file

124

file_permission: Security descriptor string or permission key

125

file_permission_key: Key for a previously created permission

126

lease_id: Required if file has an active lease

127

timeout: Request timeout in seconds

128

129

Returns:

130

Dict containing file creation response with ETag and properties

131

"""

132

133

def delete_file(

134

self,

135

**kwargs: Any

136

) -> None:

137

"""

138

Marks the specified file for deletion.

139

140

Parameters:

141

lease_id: Required if file has an active lease

142

timeout: Request timeout in seconds

143

"""

144

145

def rename_file(

146

self,

147

new_name: str,

148

**kwargs: Any

149

) -> ShareFileClient:

150

"""

151

Rename a file and return a client for the renamed file.

152

153

Parameters:

154

new_name: New path/name for the file

155

overwrite: Whether to overwrite existing file with same name

156

ignore_readonly: Whether to ignore readonly attribute on destination

157

file_permission: Security descriptor for the destination file

158

file_permission_key: Permission key for the destination file

159

timeout: Request timeout in seconds

160

161

Returns:

162

ShareFileClient: Client for the renamed file

163

"""

164

```

165

166

## File Upload Operations

167

168

```python { .api }

169

def upload_file(

170

self,

171

data: Union[bytes, str, Iterable[AnyStr], IO[AnyStr]],

172

length: Optional[int] = None,

173

**kwargs: Any

174

) -> Dict[str, Any]:

175

"""

176

Uploads a new file or overwrites an existing file.

177

178

Parameters:

179

data: File content to upload

180

length: Length of the data in bytes (required for streams)

181

overwrite: Whether to overwrite existing file (default: False)

182

max_concurrency: Number of parallel upload threads (default: 1)

183

content_settings: ContentSettings object with HTTP properties

184

metadata: Dict of name-value pairs for file metadata

185

validate_content: Whether to validate content with MD5 hash

186

file_attributes: File attributes (NTFSAttributes)

187

file_creation_time: Creation time for the file

188

file_last_write_time: Last write time for the file

189

file_permission: Security descriptor string or permission key

190

file_permission_key: Key for a previously created permission

191

lease_id: Required if file has an active lease

192

timeout: Request timeout in seconds

193

194

Returns:

195

Dict containing upload response with ETag and properties

196

"""

197

198

def upload_range(

199

self,

200

data: bytes,

201

offset: int,

202

length: int,

203

**kwargs: Any

204

) -> Dict[str, Any]:

205

"""

206

Upload a range of bytes to a file.

207

208

Parameters:

209

data: Bytes to upload

210

offset: Start position in the file

211

length: Number of bytes to upload

212

validate_content: Whether to validate content with MD5 hash

213

lease_id: Required if file has an active lease

214

timeout: Request timeout in seconds

215

216

Returns:

217

Dict containing range upload response

218

"""

219

220

def upload_range_from_url(

221

self,

222

source_url: str,

223

offset: int,

224

length: int,

225

source_offset: int,

226

**kwargs: Any

227

) -> Dict[str, Any]:

228

"""

229

Writes bytes from one Azure File endpoint into a range of another file.

230

231

Parameters:

232

source_url: URL of the source file (can include SAS token)

233

offset: Start position in the destination file

234

length: Number of bytes to copy

235

source_offset: Start position in the source file

236

timeout: Request timeout in seconds

237

238

Returns:

239

Dict containing range upload response

240

"""

241

```

242

243

## File Download Operations

244

245

```python { .api }

246

def download_file(

247

self,

248

offset: Optional[int] = None,

249

length: Optional[int] = None,

250

**kwargs: Any

251

) -> StorageStreamDownloader:

252

"""

253

Downloads a file to a StorageStreamDownloader.

254

255

Parameters:

256

offset: Start position to download from

257

length: Number of bytes to download

258

validate_content: Whether to validate content with MD5 hash

259

max_concurrency: Number of parallel download threads (default: 1)

260

lease_id: Required if file has an active lease

261

timeout: Request timeout in seconds

262

263

Returns:

264

StorageStreamDownloader: Stream object for downloading file content

265

"""

266

```

267

268

## File Copy Operations

269

270

```python { .api }

271

def start_copy_from_url(

272

self,

273

source_url: str,

274

**kwargs: Any

275

) -> Dict[str, Any]:

276

"""

277

Initiates copying data from a source URL into the file.

278

279

Parameters:

280

source_url: URL of the source file (can include SAS token)

281

metadata: Dict of name-value pairs for destination file metadata

282

file_permission: Security descriptor for destination file

283

file_permission_key: Permission key for destination file

284

ignore_readonly: Whether to ignore readonly attribute on destination

285

file_attributes: File attributes for destination file

286

file_creation_time: Creation time for destination file

287

file_last_write_time: Last write time for destination file

288

lease_id: Required if destination file has an active lease

289

timeout: Request timeout in seconds

290

291

Returns:

292

Dict containing copy operation details including copy_id

293

"""

294

295

def abort_copy(

296

self,

297

copy_id: Union[str, FileProperties],

298

**kwargs: Any

299

) -> None:

300

"""

301

Aborts a pending copy operation and leaves destination file with zero length.

302

303

Parameters:

304

copy_id: Copy identifier from start_copy_from_url response

305

lease_id: Required if file has an active lease

306

timeout: Request timeout in seconds

307

"""

308

```

309

310

## File Properties and Metadata

311

312

```python { .api }

313

def get_file_properties(

314

self,

315

**kwargs: Any

316

) -> FileProperties:

317

"""

318

Returns all user-defined metadata, standard HTTP properties, and system properties.

319

320

Parameters:

321

timeout: Request timeout in seconds

322

323

Returns:

324

FileProperties: Object containing all file properties

325

"""

326

327

def set_http_headers(

328

self,

329

content_settings: ContentSettings,

330

file_attributes: Optional[Union[str, NTFSAttributes]] = None,

331

file_creation_time: Optional[Union[str, datetime]] = None,

332

file_last_write_time: Optional[Union[str, datetime]] = None,

333

file_permission: Optional[str] = None,

334

permission_key: Optional[str] = None,

335

*,

336

lease: Optional[Union[ShareLeaseClient, str]] = None,

337

**kwargs: Any

338

) -> Dict[str, Any]:

339

"""

340

Sets system properties on the file.

341

342

Parameters:

343

content_settings: ContentSettings object with HTTP properties

344

file_attributes: File attributes (NTFSAttributes)

345

file_creation_time: Creation time for the file

346

file_last_write_time: Last write time for the file

347

file_permission: Security descriptor string or permission key

348

permission_key: Key for a previously created permission

349

lease: Required if file has an active lease

350

**kwargs: Additional keyword arguments

351

352

Returns:

353

Dict containing response with ETag and last modified time

354

"""

355

356

def set_file_metadata(

357

self,

358

metadata: Optional[Dict[str, Any]] = None,

359

**kwargs: Any

360

) -> Dict[str, Any]:

361

"""

362

Sets user-defined metadata for the file.

363

364

Parameters:

365

metadata: Dict of name-value pairs (keys must be valid metadata names)

366

lease_id: Required if file has an active lease

367

timeout: Request timeout in seconds

368

369

Returns:

370

Dict containing response with ETag and last modified time

371

"""

372

```

373

374

## Range Operations

375

376

```python { .api }

377

def get_ranges(

378

self,

379

offset: Optional[int] = None,

380

length: Optional[int] = None,

381

**kwargs: Any

382

) -> List[Dict[str, int]]:

383

"""

384

Returns the list of valid page ranges for a file.

385

386

Parameters:

387

offset: Start position to get ranges from

388

length: Number of bytes to get ranges for

389

lease_id: Required if file has an active lease

390

timeout: Request timeout in seconds

391

392

Returns:

393

List[Dict]: List of range dicts with 'start' and 'end' keys

394

"""

395

396

def get_ranges_diff(

397

self,

398

previous_sharesnapshot: Union[str, Dict[str, Any]],

399

offset: Optional[int] = None,

400

length: Optional[int] = None,

401

*,

402

include_renames: Optional[bool] = None,

403

**kwargs: Any

404

) -> Tuple[List[Dict[str, int]], List[Dict[str, int]]]:

405

"""

406

Returns ranges that differ between a previous snapshot and current file.

407

408

Parameters:

409

previous_sharesnapshot: Snapshot identifier to compare against

410

offset: Start position to compare from

411

length: Number of bytes to compare

412

include_renames: Whether to include renamed ranges in the response

413

**kwargs: Additional keyword arguments

414

415

Returns:

416

Tuple[List, List]: (changed_ranges, cleared_ranges)

417

"""

418

419

def clear_range(

420

self,

421

offset: int,

422

length: int,

423

**kwargs: Any

424

) -> Dict[str, Any]:

425

"""

426

Clears the specified range and releases space used in storage.

427

428

Parameters:

429

offset: Start position of the range to clear

430

length: Number of bytes to clear

431

lease_id: Required if file has an active lease

432

timeout: Request timeout in seconds

433

434

Returns:

435

Dict containing response with ETag and last modified time

436

"""

437

438

def resize_file(

439

self,

440

size: int,

441

**kwargs: Any

442

) -> Dict[str, Any]:

443

"""

444

Resizes a file to the specified size.

445

446

Parameters:

447

size: New size of the file in bytes

448

lease_id: Required if file has an active lease

449

timeout: Request timeout in seconds

450

451

Returns:

452

Dict containing response with ETag and last modified time

453

"""

454

```

455

456

## Handle Management

457

458

```python { .api }

459

def list_handles(

460

self,

461

**kwargs: Any

462

) -> ItemPaged[Handle]:

463

"""

464

Lists handles for the file.

465

466

Parameters:

467

marker: Continuation token for pagination

468

results_per_page: Maximum handles per page

469

timeout: Request timeout in seconds

470

471

Returns:

472

ItemPaged[Handle]: Paginated list of open handles

473

"""

474

475

def close_handle(

476

self,

477

handle: Union[str, Handle],

478

**kwargs: Any

479

) -> Dict[str, int]:

480

"""

481

Closes an open file handle.

482

483

Parameters:

484

handle: Handle ID string or Handle object to close

485

timeout: Request timeout in seconds

486

487

Returns:

488

Dict containing number of handles closed

489

"""

490

491

def close_all_handles(

492

self,

493

**kwargs: Any

494

) -> Dict[str, int]:

495

"""

496

Closes all handles for the file.

497

498

Parameters:

499

timeout: Request timeout in seconds

500

501

Returns:

502

Dict containing number of handles closed

503

"""

504

```

505

506

## Advanced File Operations

507

508

```python { .api }

509

def create_hardlink(

510

self,

511

target: str,

512

*,

513

lease: Optional[Union[ShareLeaseClient, str]] = None,

514

**kwargs: Any

515

) -> Dict[str, Any]:

516

"""

517

Create a hard link to an existing file.

518

519

Parameters:

520

target: Path for the new hard link

521

lease: Required if file has an active lease

522

**kwargs: Additional keyword arguments

523

524

Returns:

525

Dict[str, Any]: Response containing operation metadata

526

"""

527

528

def create_symlink(

529

self,

530

target: str,

531

*,

532

metadata: Optional[Dict[str, str]] = None,

533

**kwargs: Any

534

) -> Dict[str, Any]:

535

"""

536

Create a symbolic link to an existing file or directory.

537

538

Parameters:

539

target: Path to the target file or directory

540

metadata: Metadata for the symbolic link

541

**kwargs: Additional keyword arguments

542

543

Returns:

544

Dict[str, Any]: Response containing operation metadata

545

"""

546

547

def get_symlink(

548

self,

549

**kwargs: Any

550

) -> Dict[str, Any]:

551

"""

552

Get the target of a symbolic link.

553

554

Parameters:

555

**kwargs: Additional keyword arguments

556

557

Returns:

558

Dict[str, Any]: Response containing symlink target and metadata

559

"""

560

```

561

562

## Lease Management

563

564

```python { .api }

565

def acquire_lease(

566

self,

567

lease_id: Optional[str] = None,

568

**kwargs: Any

569

) -> ShareLeaseClient:

570

"""

571

Requests a new lease for the file.

572

573

Parameters:

574

lease_id: Proposed lease ID (UUID format)

575

lease_duration: Duration of the lease in seconds (-1 for infinite)

576

timeout: Request timeout in seconds

577

578

Returns:

579

ShareLeaseClient: Lease client for managing the lease

580

"""

581

```

582

583

## Properties

584

585

```python { .api }

586

@property

587

def url(self) -> str:

588

"""The full endpoint URL to the file."""

589

590

@property

591

def share_name(self) -> str:

592

"""The name of the share containing this file."""

593

594

@property

595

def file_path(self) -> str:

596

"""The path to the file with which to interact."""

597

598

@property

599

def snapshot(self) -> Optional[str]:

600

"""An optional share snapshot on which to operate."""

601

602

@property

603

def account_name(self) -> str:

604

"""The storage account name."""

605

606

@property

607

def credential(self) -> Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, TokenCredential]:

608

"""The credential used to authenticate."""

609

```

610

611

## Usage Examples

612

613

### Basic File Operations

614

615

```python { .api }

616

from azure.storage.fileshare import ShareFileClient, ContentSettings

617

from azure.core.credentials import AzureNamedKeyCredential

618

619

# Initialize file client

620

credential = AzureNamedKeyCredential("myaccount", "mykey")

621

file_client = ShareFileClient(

622

account_url="https://myaccount.file.core.windows.net",

623

share_name="documents",

624

file_path="reports/monthly_report.pdf",

625

credential=credential

626

)

627

628

# Check if file exists

629

if file_client.exists():

630

print("File already exists")

631

else:

632

print("File does not exist")

633

634

# Upload a new file

635

with open("local_report.pdf", "rb") as data:

636

upload_response = file_client.upload_file(

637

data=data,

638

overwrite=True,

639

content_settings=ContentSettings(

640

content_type="application/pdf",

641

content_disposition="attachment; filename=monthly_report.pdf"

642

),

643

metadata={"department": "finance", "month": "january", "year": "2024"}

644

)

645

print(f"File uploaded with ETag: {upload_response['etag']}")

646

```

647

648

### File Download and Content Processing

649

650

```python { .api }

651

# Download entire file

652

download_stream = file_client.download_file()

653

654

# Method 1: Download to bytes

655

file_content = download_stream.readall()

656

print(f"Downloaded {len(file_content)} bytes")

657

658

# Method 2: Download to local file

659

with open("downloaded_report.pdf", "wb") as file_handle:

660

download_stream.readinto(file_handle)

661

662

# Method 3: Download with parallel connections

663

download_stream = file_client.download_file(max_concurrency=4)

664

content = download_stream.content_as_bytes(max_concurrency=4)

665

666

# Partial download (range)

667

partial_stream = file_client.download_file(offset=0, length=1024) # First 1KB

668

first_chunk = partial_stream.readall()

669

670

# Download and process as text

671

text_file_client = ShareFileClient(

672

account_url="https://myaccount.file.core.windows.net",

673

share_name="documents",

674

file_path="config.txt",

675

credential=credential

676

)

677

678

text_stream = text_file_client.download_file()

679

text_content = text_stream.content_as_text(encoding="utf-8")

680

print(f"File content:\n{text_content}")

681

```

682

683

### Advanced Upload Scenarios

684

685

```python { .api }

686

from azure.storage.fileshare import NTFSAttributes

687

from datetime import datetime, timezone

688

689

# Large file upload with progress tracking

690

def upload_large_file(file_client, local_path, chunk_size=4*1024*1024):

691

"""Upload large file in chunks with progress."""

692

import os

693

694

file_size = os.path.getsize(local_path)

695

696

# Create empty file first

697

file_client.create_file(file_size)

698

699

with open(local_path, "rb") as file_handle:

700

offset = 0

701

while offset < file_size:

702

chunk = file_handle.read(chunk_size)

703

if not chunk:

704

break

705

706

file_client.upload_range(

707

data=chunk,

708

offset=offset,

709

length=len(chunk)

710

)

711

712

offset += len(chunk)

713

progress = (offset / file_size) * 100

714

print(f"Upload progress: {progress:.1f}%")

715

716

# Upload with custom attributes

717

upload_response = file_client.upload_file(

718

data=b"Sample file content",

719

overwrite=True,

720

file_attributes=NTFSAttributes.Archive | NTFSAttributes.ReadOnly,

721

file_creation_time=datetime(2024, 1, 1, tzinfo=timezone.utc),

722

file_last_write_time=datetime.now(timezone.utc),

723

validate_content=True # Validates MD5 hash

724

)

725

```

726

727

### File Copy and Backup Operations

728

729

```python { .api }

730

# Copy file from another Azure file share

731

source_url = "https://sourceaccount.file.core.windows.net/source-share/file.txt"

732

source_sas = "?sp=r&st=2024-01-01T00:00:00Z&se=2024-12-31T23:59:59Z&sv=2021-06-08&sr=f&sig=..."

733

734

copy_response = file_client.start_copy_from_url(

735

source_url=source_url + source_sas,

736

metadata={"copied_from": "backup_share", "copy_date": datetime.now().isoformat()}

737

)

738

739

copy_id = copy_response['copy_id']

740

print(f"Copy started with ID: {copy_id}")

741

742

# Monitor copy progress

743

import time

744

while True:

745

properties = file_client.get_file_properties()

746

copy_status = properties.copy.status

747

print(f"Copy status: {copy_status}")

748

749

if copy_status == 'success':

750

print("Copy completed successfully")

751

break

752

elif copy_status == 'failed':

753

print(f"Copy failed: {properties.copy.status_description}")

754

break

755

756

time.sleep(5) # Check again in 5 seconds

757

758

# Copy between ranges

759

source_file_client = ShareFileClient(

760

account_url="https://myaccount.file.core.windows.net",

761

share_name="source",

762

file_path="large_file.bin",

763

credential=credential

764

)

765

766

# Copy specific range from source to destination

767

file_client.upload_range_from_url(

768

source_url=source_file_client.url + "?" + sas_token,

769

offset=0, # Destination offset

770

length=1024*1024, # 1MB

771

source_offset=5*1024*1024 # Start from 5MB in source

772

)

773

```

774

775

### Range Operations and File Manipulation

776

777

```python { .api }

778

# Get file ranges (for sparse files)

779

ranges = file_client.get_ranges()

780

print("File ranges:")

781

for range_info in ranges:

782

print(f" {range_info['start']}-{range_info['end']} ({range_info['end'] - range_info['start'] + 1} bytes)")

783

784

# Clear a range (create a hole in the file)

785

file_client.clear_range(offset=1024, length=2048)

786

787

# Compare with snapshot

788

snapshot_client = ShareFileClient(

789

account_url="https://myaccount.file.core.windows.net",

790

share_name="documents",

791

file_path="reports/monthly_report.pdf",

792

snapshot="2024-01-01T00:00:00Z",

793

credential=credential

794

)

795

796

changed_ranges, cleared_ranges = file_client.get_ranges_diff(

797

previous_sharesnapshot="2024-01-01T00:00:00Z"

798

)

799

print(f"Changed ranges: {len(changed_ranges)}")

800

print(f"Cleared ranges: {len(cleared_ranges)}")

801

802

# Resize file

803

current_size = file_client.get_file_properties().size

804

new_size = current_size + 1024*1024 # Add 1MB

805

file_client.resize_file(new_size)

806

print(f"File resized from {current_size} to {new_size} bytes")

807

```

808

809

### Metadata and Properties Management

810

811

```python { .api }

812

# Get comprehensive file properties

813

properties = file_client.get_file_properties()

814

print(f"File: {properties.name}")

815

print(f"Size: {properties.size} bytes")

816

print(f"Content type: {properties.content_settings.content_type}")

817

print(f"Last modified: {properties.last_modified}")

818

print(f"ETag: {properties.etag}")

819

print(f"Metadata: {properties.metadata}")

820

print(f"Attributes: {properties.file_attributes}")

821

print(f"Creation time: {properties.creation_time}")

822

823

# Update HTTP headers

824

file_client.set_http_headers(

825

content_settings=ContentSettings(

826

content_type="application/json",

827

content_encoding="gzip",

828

content_language="en-US",

829

cache_control="max-age=3600"

830

)

831

)

832

833

# Update metadata

834

file_client.set_file_metadata({

835

"processed": "true",

836

"processing_date": datetime.now().isoformat(),

837

"version": "2.1",

838

"checksum": "abc123def456"

839

})

840

```

841

842

### Handle Management for Open Files

843

844

```python { .api }

845

# List open handles on the file

846

handles = list(file_client.list_handles())

847

print(f"File has {len(handles)} open handle(s)")

848

849

for handle in handles:

850

print(f"Handle {handle.id}:")

851

print(f" Client: {handle.client_name} ({handle.client_ip})")

852

print(f" Session: {handle.session_id}")

853

print(f" Opened: {handle.open_time}")

854

print(f" Access: {handle.access_rights}")

855

856

# Close specific handle (useful for releasing locks)

857

if handles:

858

result = file_client.close_handle(handles[0])

859

print(f"Closed {result['closed_handles_count']} handle(s)")

860

861

# Close all handles (useful for maintenance)

862

result = file_client.close_all_handles()

863

print(f"Closed {result['closed_handles_count']} total handle(s)")

864

```

865

866

### Symbolic Links and Hard Links

867

868

```python { .api }

869

# Create symbolic link

870

symlink_client = file_client.create_symlink(

871

target_path="../../shared/template.docx",

872

file_attributes=NTFSAttributes.ReparsePoint

873

)

874

print(f"Symbolic link created: {symlink_client.file_path}")

875

876

# Get symlink target

877

target = symlink_client.get_symlink()

878

print(f"Symlink points to: {target}")

879

880

# Create hard link (multiple names for same file)

881

hardlink_client = file_client.create_hardlink("backup_copy.pdf")

882

print(f"Hard link created: {hardlink_client.file_path}")

883

884

# Both clients point to the same file content

885

original_props = file_client.get_file_properties()

886

hardlink_props = hardlink_client.get_file_properties()

887

print(f"Same file ID: {original_props.file_id == hardlink_props.file_id}")

888

```

889

890

### Lease Management for Exclusive Access

891

892

```python { .api }

893

# Acquire lease for exclusive access

894

lease_client = file_client.acquire_lease(lease_duration=60) # 60 second lease

895

print(f"Lease acquired: {lease_client.id}")

896

897

try:

898

# Perform operations with lease

899

file_client.set_file_metadata(

900

{"locked_by": "batch_process", "lock_time": datetime.now().isoformat()},

901

lease_id=lease_client.id

902

)

903

904

# Upload new content (requires lease)

905

file_client.upload_file(

906

data=b"Updated content with exclusive access",

907

overwrite=True,

908

lease_id=lease_client.id

909

)

910

911

finally:

912

# Always release the lease

913

lease_client.release()

914

print("Lease released")

915

```

916

917

### Error Handling and Recovery

918

919

```python { .api }

920

from azure.core.exceptions import ResourceExistsError, ResourceNotFoundError, HttpResponseError

921

922

# Safe file operations with error handling

923

try:

924

# Try to upload file

925

file_client.upload_file(data=b"content", overwrite=False)

926

except ResourceExistsError:

927

print("File exists, checking if update is needed...")

928

properties = file_client.get_file_properties()

929

if properties.size == 0:

930

# Empty file, safe to overwrite

931

file_client.upload_file(data=b"content", overwrite=True)

932

else:

933

print("File has content, skipping upload")

934

935

# Handle copy operation errors

936

try:

937

copy_response = file_client.start_copy_from_url(source_url)

938

copy_id = copy_response['copy_id']

939

940

# Monitor and handle copy failure

941

properties = file_client.get_file_properties()

942

if properties.copy.status == 'failed':

943

print(f"Copy failed: {properties.copy.status_description}")

944

file_client.abort_copy(copy_id)

945

946

except HttpResponseError as e:

947

if e.error_code == "CannotVerifyCopySource":

948

print("Source file not accessible or SAS token expired")

949

else:

950

print(f"Copy operation failed: {e.message}")

951

952

# Retry logic for transient failures

953

import time

954

from azure.core.exceptions import ServiceRequestError

955

956

def upload_with_retry(file_client, data, max_retries=3):

957

"""Upload with exponential backoff retry."""

958

for attempt in range(max_retries):

959

try:

960

return file_client.upload_file(data, overwrite=True)

961

except ServiceRequestError as e:

962

if attempt < max_retries - 1:

963

wait_time = 2 ** attempt # Exponential backoff

964

print(f"Upload failed, retrying in {wait_time} seconds...")

965

time.sleep(wait_time)

966

else:

967

raise

968

```

969

970

The ShareFileClient provides comprehensive file management capabilities, enabling efficient file operations, content management, and advanced features like leasing and symbolic links for Azure File Share storage.