azure-storage-file-share-ts
Azure File Share JavaScript/TypeScript SDK (@azure/storage-file-share) for SMB file share operations. Use for creating shares, managing directories, uploading/downloading files, and handling file metadata. Supports Azure Files SMB protocol scenarios. Triggers: "file share", "@azu
Install
npx skills add https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-typescript/skills/azure-storage-file-share-ts
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install microsoft-skills@llmmart
git clone https://github.com/microsoft/skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole microsoft/skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
@azure/storage-file-share (TypeScript/JavaScript)
SDK for Azure File Share operations — SMB file shares, directories, and file operations.
Installation
npm install @azure/storage-file-share @azure/identity
Current Version: 12.x
Node.js: >= 18.0.0
Environment Variables
AZURE_STORAGE_ACCOUNT_NAME=<account-name>
AZURE_STORAGE_ACCOUNT_KEY=<account-key>
# OR connection string
AZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=...
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production
Authentication
Connection String (Simplest)
import { ShareServiceClient } from "@azure/storage-file-share";
const client = ShareServiceClient.fromConnectionString(
process.env.AZURE_STORAGE_CONNECTION_STRING!
);
StorageSharedKeyCredential (Node.js only)
import { ShareServiceClient, StorageSharedKeyCredential } from "@azure/storage-file-share";
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;
const accountKey = process.env.AZURE_STORAGE_ACCOUNT_KEY!;
const sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);
const client = new ShareServiceClient(
`https://${accountName}.file.core.windows.net`,
sharedKeyCredential
);
Microsoft Entra Token Credential
import { ShareServiceClient } from "@azure/storage-file-share";
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";
// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
const credential = new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]});
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/javascript/api/overview/azure/identity-readme?view=azure-node-latest#credential-classes
// const credential = new ManagedIdentityCredential();
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;
const client = new ShareServiceClient(
`https://${accountName}.file.core.windows.net`,
credential
);
SAS Token
import { ShareServiceClient } from "@azure/storage-file-share";
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;
const sasToken = process.env.AZURE_STORAGE_SAS_TOKEN!;
const client = new ShareServiceClient(
`https://${accountName}.file.core.windows.net${sasToken}`
);
Client Hierarchy
ShareServiceClient (account level)
└── ShareClient (share level)
└── ShareDirectoryClient (directory level)
└── ShareFileClient (file level)
Share Operations
Create Share
const shareClient = client.getShareClient("my-share");
await shareClient.create();
// Create with quota (in GB)
await shareClient.create({ quota: 100 });
List Shares
for await (const share of client.listShares()) {
console.log(share.name, share.properties.quota);
}
// With prefix filter
for await (const share of client.listShares({ prefix: "logs-" })) {
console.log(share.name);
}
Delete Share
await shareClient.delete();
// Delete if exists
await shareClient.deleteIfExists();
Get Share Properties
const properties = await shareClient.getProperties();
console.log("Quota:", properties.quota, "GB");
console.log("Last Modified:", properties.lastModified);
Set Share Quota
await shareClient.setQuota(200); // 200 GB
Directory Operations
Create Directory
const directoryClient = shareClient.getDirectoryClient("my-directory");
await directoryClient.create();
// Create nested directory
const nestedDir = shareClient.getDirectoryClient("parent/child/grandchild");
await nestedDir.create();
List Directories and Files
const directoryClient = shareClient.getDirectoryClient("my-directory");
for await (const item of directoryClient.listFilesAndDirectories()) {
if (item.kind === "directory") {
console.log(`[DIR] ${item.name}`);
} else {
console.log(`[FILE] ${item.name} (${item.properties.contentLength} bytes)`);
}
}
Delete Directory
await directoryClient.delete();
// Delete if exists
await directoryClient.deleteIfExists();
Check if Directory Exists
const exists = await directoryClient.exists();
if (!exists) {
await directoryClient.create();
}
File Operations
Upload File (Simple)
const fileClient = shareClient
.getDirectoryClient("my-directory")
.getFileClient("my-file.txt");
// Upload string
const content = "Hello, World!";
await fileClient.create(content.length);
await fileClient.uploadRange(content, 0, content.length);
Upload File (Node.js - from local file)
import * as fs from "fs";
import * as path from "path";
const fileClient = shareClient.rootDirectoryClient.getFileClient("uploaded.txt");
const localFilePath = "/path/to/local/file.txt";
const fileSize = fs.statSync(localFilePath).size;
await fileClient.create(fileSize);
await fileClient.uploadFile(localFilePath);
Upload File (Buffer)
const buffer = Buffer.from("Hello, Azure Files!");
const fileClient = shareClient.rootDirectoryClient.getFileClient("buffer-file.txt");
await fileClient.create(buffer.length);
await fileClient.uploadRange(buffer, 0, buffer.length);
Upload File (Stream)
import * as fs from "fs";
const fileClient = shareClient.rootDirectoryClient.getFileClient("streamed.txt");
const readStream = fs.createReadStream("/path/to/local/file.txt");
const fileSize = fs.statSync("/path/to/local/file.txt").size;
await fileClient.create(fileSize);
await fileClient.uploadStream(readStream, fileSize, 4 * 1024 * 1024, 4); // 4MB buffer, 4 concurrency
Download File
const fileClient = shareClient
.getDirectoryClient("my-directory")
.getFileClient("my-file.txt");
const downloadResponse = await fileClient.download();
// Read as string
const chunks: Buffer[] = [];
for await (const chunk of downloadResponse.readableStreamBody!) {
chunks.push(Buffer.from(chunk));
}
const content = Buffer.concat(chunks).toString("utf-8");
Download to File (Node.js)
const fileClient = shareClient.rootDirectoryClient.getFileClient("my-file.txt");
await fileClient.downloadToFile("/path/to/local/destination.txt");
Download to Buffer (Node.js)
const fileClient = shareClient.rootDirectoryClient.getFileClient("my-file.txt");
const buffer = await fileClient.downloadToBuffer();
console.log(buffer.toString());
Delete File
const fileClient = shareClient.rootDirectoryClient.getFileClient("my-file.txt");
await fileClient.delete();
// Delete if exists
await fileClient.deleteIfExists();
Copy File
const sourceUrl = "https://account.file.core.windows.net/share/source.txt";
const destFileClient = shareClient.rootDirectoryClient.getFileClient("destination.txt");
// Start copy operation
const copyPoller = await destFileClient.startCopyFromURL(sourceUrl);
await copyPoller.pollUntilDone();
File Properties & Metadata
Get File Properties
const fileClient = shareClient.rootDirectoryClient.getFileClient("my-file.txt");
const properties = await fileClient.getProperties();
console.log("Content-Length:", properties.contentLength);
console.log("Content-Type:", properties.contentType);
console.log("Last Modified:", properties.lastModified);
console.log("ETag:", properties.etag);
Set Metadata
await fileClient.setMetadata({
author: "John Doe",
category: "documents",
});
Set HTTP Headers
await fileClient.setHttpHeaders({
fileContentType: "text/plain",
fileCacheControl: "max-age=3600",
fileContentDisposition: "attachment; filename=download.txt",
});
Range Operations
Upload Range
const data = Buffer.from("partial content");
await fileClient.uploadRange(data, 100, data.length); // Write at offset 100
Download Range
const downloadResponse = await fileClient.download(100, 50); // offset 100, length 50
Clear Range
await fileClient.clearRange(0, 100); // Clear first 100 bytes
Snapshot Operations
Create Snapshot
const snapshotResponse = await shareClient.createSnapshot();
console.log("Snapshot:", snapshotResponse.snapshot);
Access Snapshot
const snapshotShareClient = shareClient.withSnapshot(snapshotResponse.snapshot!);
const snapshotFileClient = snapshotShareClient.rootDirectoryClient.getFileClient("file.txt");
const content = await snapshotFileClient.downloadToBuffer();
Delete Snapshot
await shareClient.delete({ deleteSnapshots: "include" });
SAS Token Generation (Node.js only)
Generate File SAS
import {
generateFileSASQueryParameters,
FileSASPermissions,
StorageSharedKeyCredential,
} from "@azure/storage-file-share";
const sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);
const sasToken = generateFileSASQueryParameters(
{
shareName: "my-share",
filePath: "my-directory/my-file.txt",
permissions: FileSASPermissions.parse("r"), // read only
expiresOn: new Date(Date.now() + 3600 * 1000), // 1 hour
},
sharedKeyCredential
).toString();
const sasUrl = `https://${accountName}.file.core.windows.net/my-share/my-directory/my-file.txt?${sasToken}`;
Generate Share SAS
import { ShareSASPermissions, generateFileSASQueryParameters } from "@azure/storage-file-share";
const sasToken = generateFileSASQueryParameters(
{
shareName: "my-share",
permissions: ShareSASPermissions.parse("rcwdl"), // read, create, write, delete, list
expiresOn: new Date(Date.now() + 24 * 3600 * 1000), // 24 hours
},
sharedKeyCredential
).toString();
Error Handling
import { RestError } from "@azure/storage-file-share";
try {
await shareClient.create();
} catch (error) {
if (error instanceof RestError) {
switch (error.statusCode) {
case 404:
console.log("Share not found");
break;
case 409:
console.log("Share already exists");
break;
case 403:
console.log("Access denied");
break;
default:
console.error(`Storage error ${error.statusCode}: ${error.message}`);
}
}
throw error;
}
TypeScript Types Reference
import {
// Clients
ShareServiceClient,
ShareClient,
ShareDirectoryClient,
ShareFileClient,
// Authentication
StorageSharedKeyCredential,
AnonymousCredential,
// SAS
FileSASPermissions,
ShareSASPermissions,
AccountSASPermissions,
AccountSASServices,
AccountSASResourceTypes,
generateFileSASQueryParameters,
generateAccountSASQueryParameters,
// Options & Responses
ShareCreateResponse,
FileDownloadResponseModel,
DirectoryItem,
FileItem,
ShareProperties,
FileProperties,
// Errors
RestError,
} from "@azure/storage-file-share";
Best Practices
- Use connection strings for simplicity — Easiest setup for development
- Use
DefaultAzureCredentialfor local development; useManagedIdentityCredentialorWorkloadIdentityCredentialfor production - Set quotas on shares — Prevent unexpected storage costs
- Use streaming for large files —
uploadStream/downloadToFilefor files > 256MB - Use ranges for partial updates — More efficient than full file replacement
- Create snapshots before major changes — Point-in-time recovery
- Handle errors gracefully — Check
RestError.statusCodefor specific handling - Use
*IfExistsmethods — For idempotent operations
Platform Differences
| Feature | Node.js | Browser |
|---|---|---|
StorageSharedKeyCredential |
✅ | ❌ |
uploadFile() |
✅ | ❌ |
uploadStream() |
✅ | ❌ |
downloadToFile() |
✅ | ❌ |
downloadToBuffer() |
✅ | ❌ |
| SAS generation | ✅ | ❌ |
| DefaultAzureCredential | ✅ | ❌ |
| Anonymous/SAS access | ✅ | ✅ |
Files (skills)
-
SKILL.md 12.5 KB
--- name: azure-storage-file-share-ts description: | Azure File Share JavaScript/TypeScript SDK (@azure/storage-file-share) for SMB file share operations. Use for creating shares, managing directories, uploading/downloading files, and handling file metadata. Supports Azure Files SMB protocol scenarios. Triggers: "file share", "@azure/storage-file-share", "ShareServiceClient", "ShareClient", "SMB", "Azure Files". license: MIT metadata: author: Microsoft version: "1.0.0" package: '@azure/storage-file-share' --- # @azure/storage-file-share (TypeScript/JavaScript) SDK for Azure File Share operations — SMB file shares, directories, and file operations. ## Installation ```bash npm install @azure/storage-file-share @azure/identity ``` **Current Version**: 12.x **Node.js**: >= 18.0.0 ## Environment Variables ```bash AZURE_STORAGE_ACCOUNT_NAME=<account-name> AZURE_STORAGE_ACCOUNT_KEY=<account-key> # OR connection string AZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=... AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production ``` ## Authentication ### Connection String (Simplest) ```typescript import { ShareServiceClient } from "@azure/storage-file-share"; const client = ShareServiceClient.fromConnectionString( process.env.AZURE_STORAGE_CONNECTION_STRING! ); ``` ### StorageSharedKeyCredential (Node.js only) ```typescript import { ShareServiceClient, StorageSharedKeyCredential } from "@azure/storage-file-share"; const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!; const accountKey = process.env.AZURE_STORAGE_ACCOUNT_KEY!; const sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey); const client = new ShareServiceClient( `https://${accountName}.file.core.windows.net`, sharedKeyCredential ); ``` ### Microsoft Entra Token Credential ```typescript import { ShareServiceClient } from "@azure/storage-file-share"; import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity"; // Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential> const credential = new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]}); // Or use a specific credential directly in production: // See https://learn.microsoft.com/javascript/api/overview/azure/identity-readme?view=azure-node-latest#credential-classes // const credential = new ManagedIdentityCredential(); const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!; const client = new ShareServiceClient( `https://${accountName}.file.core.windows.net`, credential ); ``` ### SAS Token ```typescript import { ShareServiceClient } from "@azure/storage-file-share"; const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!; const sasToken = process.env.AZURE_STORAGE_SAS_TOKEN!; const client = new ShareServiceClient( `https://${accountName}.file.core.windows.net${sasToken}` ); ``` ## Client Hierarchy ``` ShareServiceClient (account level) └── ShareClient (share level) └── ShareDirectoryClient (directory level) └── ShareFileClient (file level) ``` ## Share Operations ### Create Share ```typescript const shareClient = client.getShareClient("my-share"); await shareClient.create(); // Create with quota (in GB) await shareClient.create({ quota: 100 }); ``` ### List Shares ```typescript for await (const share of client.listShares()) { console.log(share.name, share.properties.quota); } // With prefix filter for await (const share of client.listShares({ prefix: "logs-" })) { console.log(share.name); } ``` ### Delete Share ```typescript await shareClient.delete(); // Delete if exists await shareClient.deleteIfExists(); ``` ### Get Share Properties ```typescript const properties = await shareClient.getProperties(); console.log("Quota:", properties.quota, "GB"); console.log("Last Modified:", properties.lastModified); ``` ### Set Share Quota ```typescript await shareClient.setQuota(200); // 200 GB ``` ## Directory Operations ### Create Directory ```typescript const directoryClient = shareClient.getDirectoryClient("my-directory"); await directoryClient.create(); // Create nested directory const nestedDir = shareClient.getDirectoryClient("parent/child/grandchild"); await nestedDir.create(); ``` ### List Directories and Files ```typescript const directoryClient = shareClient.getDirectoryClient("my-directory"); for await (const item of directoryClient.listFilesAndDirectories()) { if (item.kind === "directory") { console.log(`[DIR] ${item.name}`); } else { console.log(`[FILE] ${item.name} (${item.properties.contentLength} bytes)`); } } ``` ### Delete Directory ```typescript await directoryClient.delete(); // Delete if exists await directoryClient.deleteIfExists(); ``` ### Check if Directory Exists ```typescript const exists = await directoryClient.exists(); if (!exists) { await directoryClient.create(); } ``` ## File Operations ### Upload File (Simple) ```typescript const fileClient = shareClient .getDirectoryClient("my-directory") .getFileClient("my-file.txt"); // Upload string const content = "Hello, World!"; await fileClient.create(content.length); await fileClient.uploadRange(content, 0, content.length); ``` ### Upload File (Node.js - from local file) ```typescript import * as fs from "fs"; import * as path from "path"; const fileClient = shareClient.rootDirectoryClient.getFileClient("uploaded.txt"); const localFilePath = "/path/to/local/file.txt"; const fileSize = fs.statSync(localFilePath).size; await fileClient.create(fileSize); await fileClient.uploadFile(localFilePath); ``` ### Upload File (Buffer) ```typescript const buffer = Buffer.from("Hello, Azure Files!"); const fileClient = shareClient.rootDirectoryClient.getFileClient("buffer-file.txt"); await fileClient.create(buffer.length); await fileClient.uploadRange(buffer, 0, buffer.length); ``` ### Upload File (Stream) ```typescript import * as fs from "fs"; const fileClient = shareClient.rootDirectoryClient.getFileClient("streamed.txt"); const readStream = fs.createReadStream("/path/to/local/file.txt"); const fileSize = fs.statSync("/path/to/local/file.txt").size; await fileClient.create(fileSize); await fileClient.uploadStream(readStream, fileSize, 4 * 1024 * 1024, 4); // 4MB buffer, 4 concurrency ``` ### Download File ```typescript const fileClient = shareClient .getDirectoryClient("my-directory") .getFileClient("my-file.txt"); const downloadResponse = await fileClient.download(); // Read as string const chunks: Buffer[] = []; for await (const chunk of downloadResponse.readableStreamBody!) { chunks.push(Buffer.from(chunk)); } const content = Buffer.concat(chunks).toString("utf-8"); ``` ### Download to File (Node.js) ```typescript const fileClient = shareClient.rootDirectoryClient.getFileClient("my-file.txt"); await fileClient.downloadToFile("/path/to/local/destination.txt"); ``` ### Download to Buffer (Node.js) ```typescript const fileClient = shareClient.rootDirectoryClient.getFileClient("my-file.txt"); const buffer = await fileClient.downloadToBuffer(); console.log(buffer.toString()); ``` ### Delete File ```typescript const fileClient = shareClient.rootDirectoryClient.getFileClient("my-file.txt"); await fileClient.delete(); // Delete if exists await fileClient.deleteIfExists(); ``` ### Copy File ```typescript const sourceUrl = "https://account.file.core.windows.net/share/source.txt"; const destFileClient = shareClient.rootDirectoryClient.getFileClient("destination.txt"); // Start copy operation const copyPoller = await destFileClient.startCopyFromURL(sourceUrl); await copyPoller.pollUntilDone(); ``` ## File Properties & Metadata ### Get File Properties ```typescript const fileClient = shareClient.rootDirectoryClient.getFileClient("my-file.txt"); const properties = await fileClient.getProperties(); console.log("Content-Length:", properties.contentLength); console.log("Content-Type:", properties.contentType); console.log("Last Modified:", properties.lastModified); console.log("ETag:", properties.etag); ``` ### Set Metadata ```typescript await fileClient.setMetadata({ author: "John Doe", category: "documents", }); ``` ### Set HTTP Headers ```typescript await fileClient.setHttpHeaders({ fileContentType: "text/plain", fileCacheControl: "max-age=3600", fileContentDisposition: "attachment; filename=download.txt", }); ``` ## Range Operations ### Upload Range ```typescript const data = Buffer.from("partial content"); await fileClient.uploadRange(data, 100, data.length); // Write at offset 100 ``` ### Download Range ```typescript const downloadResponse = await fileClient.download(100, 50); // offset 100, length 50 ``` ### Clear Range ```typescript await fileClient.clearRange(0, 100); // Clear first 100 bytes ``` ## Snapshot Operations ### Create Snapshot ```typescript const snapshotResponse = await shareClient.createSnapshot(); console.log("Snapshot:", snapshotResponse.snapshot); ``` ### Access Snapshot ```typescript const snapshotShareClient = shareClient.withSnapshot(snapshotResponse.snapshot!); const snapshotFileClient = snapshotShareClient.rootDirectoryClient.getFileClient("file.txt"); const content = await snapshotFileClient.downloadToBuffer(); ``` ### Delete Snapshot ```typescript await shareClient.delete({ deleteSnapshots: "include" }); ``` ## SAS Token Generation (Node.js only) ### Generate File SAS ```typescript import { generateFileSASQueryParameters, FileSASPermissions, StorageSharedKeyCredential, } from "@azure/storage-file-share"; const sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey); const sasToken = generateFileSASQueryParameters( { shareName: "my-share", filePath: "my-directory/my-file.txt", permissions: FileSASPermissions.parse("r"), // read only expiresOn: new Date(Date.now() + 3600 * 1000), // 1 hour }, sharedKeyCredential ).toString(); const sasUrl = `https://${accountName}.file.core.windows.net/my-share/my-directory/my-file.txt?${sasToken}`; ``` ### Generate Share SAS ```typescript import { ShareSASPermissions, generateFileSASQueryParameters } from "@azure/storage-file-share"; const sasToken = generateFileSASQueryParameters( { shareName: "my-share", permissions: ShareSASPermissions.parse("rcwdl"), // read, create, write, delete, list expiresOn: new Date(Date.now() + 24 * 3600 * 1000), // 24 hours }, sharedKeyCredential ).toString(); ``` ## Error Handling ```typescript import { RestError } from "@azure/storage-file-share"; try { await shareClient.create(); } catch (error) { if (error instanceof RestError) { switch (error.statusCode) { case 404: console.log("Share not found"); break; case 409: console.log("Share already exists"); break; case 403: console.log("Access denied"); break; default: console.error(`Storage error ${error.statusCode}: ${error.message}`); } } throw error; } ``` ## TypeScript Types Reference ```typescript import { // Clients ShareServiceClient, ShareClient, ShareDirectoryClient, ShareFileClient, // Authentication StorageSharedKeyCredential, AnonymousCredential, // SAS FileSASPermissions, ShareSASPermissions, AccountSASPermissions, AccountSASServices, AccountSASResourceTypes, generateFileSASQueryParameters, generateAccountSASQueryParameters, // Options & Responses ShareCreateResponse, FileDownloadResponseModel, DirectoryItem, FileItem, ShareProperties, FileProperties, // Errors RestError, } from "@azure/storage-file-share"; ``` ## Best Practices 1. **Use connection strings for simplicity** — Easiest setup for development 2. **Use `DefaultAzureCredential` for local development; use `ManagedIdentityCredential` or `WorkloadIdentityCredential` for production** 3. **Set quotas on shares** — Prevent unexpected storage costs 4. **Use streaming for large files** — `uploadStream`/`downloadToFile` for files > 256MB 5. **Use ranges for partial updates** — More efficient than full file replacement 6. **Create snapshots before major changes** — Point-in-time recovery 7. **Handle errors gracefully** — Check `RestError.statusCode` for specific handling 8. **Use `*IfExists` methods** — For idempotent operations ## Platform Differences | Feature | Node.js | Browser | |---------|---------|---------| | `StorageSharedKeyCredential` | ✅ | ❌ | | `uploadFile()` | ✅ | ❌ | | `uploadStream()` | ✅ | ❌ | | `downloadToFile()` | ✅ | ❌ | | `downloadToBuffer()` | ✅ | ❌ | | SAS generation | ✅ | ❌ | | DefaultAzureCredential | ✅ | ❌ | | Anonymous/SAS access | ✅ | ✅ |
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.