[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6XEWR8TAS9BCYMNC0A2HZ3E":3,"skill-same:01M6XEWR8TAS9BCYMNC0A2HZ3E":61},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":35,"linkOnly":36,"markdownContent":37,"markdownBody":38,"frontMatter":39,"refName":41,"commitSha":42,"skillDirectory":43,"forksCount":14,"repositoryHtmlUrl":44,"repositoryHomepageUrl":6,"ownerHtmlUrl":45,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":46,"install":47,"resources":60},"01M6XEWR8TAS9BCYMNC0A2HZ3E","azure-storage-file-share-ts",null,"Azure File Share JavaScript\u002FTypeScript SDK (@azure\u002Fstorage-file-share) for SMB file share operations.","sapsapshen\u002Fai-memory-router","sapsapshen","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F20347959?v=4","01M6XDQEF1DP50DKF37H81J3J5","shenmian","01M6XDQEJPE41Y3DT2763X8ZJN",0,"MIT","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fcopilot\u002Fazure-storage-file-share-ts\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34],"storage","azure storage","azure","azure storage file share ts","share","file","file share","typescript","sdk","javascript","smb","operations","community","for","unknown","2026","2026-11-10 10:12:30",false,"---\nname: azure-storage-file-share-ts\ndescription: Azure File Share JavaScript\u002FTypeScript SDK (@azure\u002Fstorage-file-share) for SMB file share operations.\nrisk: unknown\nsource: community\ndate_added: '2026-02-27'\n---\n\n# @azure\u002Fstorage-file-share (TypeScript\u002FJavaScript)\n\nSDK for Azure File Share operations — SMB file shares, directories, and file operations.\n\n## Installation\n\n```bash\nnpm install @azure\u002Fstorage-file-share @azure\u002Fidentity\n```\n\n**Current Version**: 12.x  \n**Node.js**: >= 18.0.0\n\n## Environment Variables\n\n```bash\nAZURE_STORAGE_ACCOUNT_NAME=\u003Caccount-name>\nAZURE_STORAGE_ACCOUNT_KEY=\u003Caccount-key>\n# OR connection string\nAZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=...\n```\n\n## Authentication\n\n### Connection String (Simplest)\n\n```typescript\nimport { ShareServiceClient } from \"@azure\u002Fstorage-file-share\";\n\nconst client = ShareServiceClient.fromConnectionString(\n  process.env.AZURE_STORAGE_CONNECTION_STRING!\n);\n```\n\n### StorageSharedKeyCredential (Node.js only)\n\n```typescript\nimport { ShareServiceClient, StorageSharedKeyCredential } from \"@azure\u002Fstorage-file-share\";\n\nconst accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;\nconst accountKey = process.env.AZURE_STORAGE_ACCOUNT_KEY!;\n\nconst sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);\nconst client = new ShareServiceClient(\n  `https:\u002F\u002F${accountName}.file.core.windows.net`,\n  sharedKeyCredential\n);\n```\n\n### DefaultAzureCredential\n\n```typescript\nimport { ShareServiceClient } from \"@azure\u002Fstorage-file-share\";\nimport { DefaultAzureCredential } from \"@azure\u002Fidentity\";\n\nconst accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;\nconst client = new ShareServiceClient(\n  `https:\u002F\u002F${accountName}.file.core.windows.net`,\n  new DefaultAzureCredential()\n);\n```\n\n### SAS Token\n\n```typescript\nimport { ShareServiceClient } from \"@azure\u002Fstorage-file-share\";\n\nconst accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;\nconst sasToken = process.env.AZURE_STORAGE_SAS_TOKEN!;\n\nconst client = new ShareServiceClient(\n  `https:\u002F\u002F${accountName}.file.core.windows.net${sasToken}`\n);\n```\n\n## Client Hierarchy\n\n```\nShareServiceClient (account level)\n└── ShareClient (share level)\n    └── ShareDirectoryClient (directory level)\n        └── ShareFileClient (file level)\n```\n\n## Share Operations\n\n### Create Share\n\n```typescript\nconst shareClient = client.getShareClient(\"my-share\");\nawait shareClient.create();\n\n\u002F\u002F Create with quota (in GB)\nawait shareClient.create({ quota: 100 });\n```\n\n### List Shares\n\n```typescript\nfor await (const share of client.listShares()) {\n  console.log(share.name, share.properties.quota);\n}\n\n\u002F\u002F With prefix filter\nfor await (const share of client.listShares({ prefix: \"logs-\" })) {\n  console.log(share.name);\n}\n```\n\n### Delete Share\n\n```typescript\nawait shareClient.delete();\n\n\u002F\u002F Delete if exists\nawait shareClient.deleteIfExists();\n```\n\n### Get Share Properties\n\n```typescript\nconst properties = await shareClient.getProperties();\nconsole.log(\"Quota:\", properties.quota, \"GB\");\nconsole.log(\"Last Modified:\", properties.lastModified);\n```\n\n### Set Share Quota\n\n```typescript\nawait shareClient.setQuota(200); \u002F\u002F 200 GB\n```\n\n## Directory Operations\n\n### Create Directory\n\n```typescript\nconst directoryClient = shareClient.getDirectoryClient(\"my-directory\");\nawait directoryClient.create();\n\n\u002F\u002F Create nested directory\nconst nestedDir = shareClient.getDirectoryClient(\"parent\u002Fchild\u002Fgrandchild\");\nawait nestedDir.create();\n```\n\n### List Directories and Files\n\n```typescript\nconst directoryClient = shareClient.getDirectoryClient(\"my-directory\");\n\nfor await (const item of directoryClient.listFilesAndDirectories()) {\n  if (item.kind === \"directory\") {\n    console.log(`[DIR] ${item.name}`);\n  } else {\n    console.log(`[FILE] ${item.name} (${item.properties.contentLength} bytes)`);\n  }\n}\n```\n\n### Delete Directory\n\n```typescript\nawait directoryClient.delete();\n\n\u002F\u002F Delete if exists\nawait directoryClient.deleteIfExists();\n```\n\n### Check if Directory Exists\n\n```typescript\nconst exists = await directoryClient.exists();\nif (!exists) {\n  await directoryClient.create();\n}\n```\n\n## File Operations\n\n### Upload File (Simple)\n\n```typescript\nconst fileClient = shareClient\n  .getDirectoryClient(\"my-directory\")\n  .getFileClient(\"my-file.txt\");\n\n\u002F\u002F Upload string\nconst content = \"Hello, World!\";\nawait fileClient.create(content.length);\nawait fileClient.uploadRange(content, 0, content.length);\n```\n\n### Upload File (Node.js - from local file)\n\n```typescript\nimport * as fs from \"fs\";\nimport * as path from \"path\";\n\nconst fileClient = shareClient.rootDirectoryClient.getFileClient(\"uploaded.txt\");\nconst localFilePath = \"\u002Fpath\u002Fto\u002Flocal\u002Ffile.txt\";\nconst fileSize = fs.statSync(localFilePath).size;\n\nawait fileClient.create(fileSize);\nawait fileClient.uploadFile(localFilePath);\n```\n\n### Upload File (Buffer)\n\n```typescript\nconst buffer = Buffer.from(\"Hello, Azure Files!\");\nconst fileClient = shareClient.rootDirectoryClient.getFileClient(\"buffer-file.txt\");\n\nawait fileClient.create(buffer.length);\nawait fileClient.uploadRange(buffer, 0, buffer.length);\n```\n\n### Upload File (Stream)\n\n```typescript\nimport * as fs from \"fs\";\n\nconst fileClient = shareClient.rootDirectoryClient.getFileClient(\"streamed.txt\");\nconst readStream = fs.createReadStream(\"\u002Fpath\u002Fto\u002Flocal\u002Ffile.txt\");\nconst fileSize = fs.statSync(\"\u002Fpath\u002Fto\u002Flocal\u002Ffile.txt\").size;\n\nawait fileClient.create(fileSize);\nawait fileClient.uploadStream(readStream, fileSize, 4 * 1024 * 1024, 4); \u002F\u002F 4MB buffer, 4 concurrency\n```\n\n### Download File\n\n```typescript\nconst fileClient = shareClient\n  .getDirectoryClient(\"my-directory\")\n  .getFileClient(\"my-file.txt\");\n\nconst downloadResponse = await fileClient.download();\n\n\u002F\u002F Read as string\nconst chunks: Buffer[] = [];\nfor await (const chunk of downloadResponse.readableStreamBody!) {\n  chunks.push(Buffer.from(chunk));\n}\nconst content = Buffer.concat(chunks).toString(\"utf-8\");\n```\n\n### Download to File (Node.js)\n\n```typescript\nconst fileClient = shareClient.rootDirectoryClient.getFileClient(\"my-file.txt\");\nawait fileClient.downloadToFile(\"\u002Fpath\u002Fto\u002Flocal\u002Fdestination.txt\");\n```\n\n### Download to Buffer (Node.js)\n\n```typescript\nconst fileClient = shareClient.rootDirectoryClient.getFileClient(\"my-file.txt\");\nconst buffer = await fileClient.downloadToBuffer();\nconsole.log(buffer.toString());\n```\n\n### Delete File\n\n```typescript\nconst fileClient = shareClient.rootDirectoryClient.getFileClient(\"my-file.txt\");\nawait fileClient.delete();\n\n\u002F\u002F Delete if exists\nawait fileClient.deleteIfExists();\n```\n\n### Copy File\n\n```typescript\nconst sourceUrl = \"https:\u002F\u002Faccount.file.core.windows.net\u002Fshare\u002Fsource.txt\";\nconst destFileClient = shareClient.rootDirectoryClient.getFileClient(\"destination.txt\");\n\n\u002F\u002F Start copy operation\nconst copyPoller = await destFileClient.startCopyFromURL(sourceUrl);\nawait copyPoller.pollUntilDone();\n```\n\n## File Properties & Metadata\n\n### Get File Properties\n\n```typescript\nconst fileClient = shareClient.rootDirectoryClient.getFileClient(\"my-file.txt\");\nconst properties = await fileClient.getProperties();\n\nconsole.log(\"Content-Length:\", properties.contentLength);\nconsole.log(\"Content-Type:\", properties.contentType);\nconsole.log(\"Last Modified:\", properties.lastModified);\nconsole.log(\"ETag:\", properties.etag);\n```\n\n### Set Metadata\n\n```typescript\nawait fileClient.setMetadata({\n  author: \"John Doe\",\n  category: \"documents\",\n});\n```\n\n### Set HTTP Headers\n\n```typescript\nawait fileClient.setHttpHeaders({\n  fileContentType: \"text\u002Fplain\",\n  fileCacheControl: \"max-age=3600\",\n  fileContentDisposition: \"attachment; filename=download.txt\",\n});\n```\n\n## Range Operations\n\n### Upload Range\n\n```typescript\nconst data = Buffer.from(\"partial content\");\nawait fileClient.uploadRange(data, 100, data.length); \u002F\u002F Write at offset 100\n```\n\n### Download Range\n\n```typescript\nconst downloadResponse = await fileClient.download(100, 50); \u002F\u002F offset 100, length 50\n```\n\n### Clear Range\n\n```typescript\nawait fileClient.clearRange(0, 100); \u002F\u002F Clear first 100 bytes\n```\n\n## Snapshot Operations\n\n### Create Snapshot\n\n```typescript\nconst snapshotResponse = await shareClient.createSnapshot();\nconsole.log(\"Snapshot:\", snapshotResponse.snapshot);\n```\n\n### Access Snapshot\n\n```typescript\nconst snapshotShareClient = shareClient.withSnapshot(snapshotResponse.snapshot!);\nconst snapshotFileClient = snapshotShareClient.rootDirectoryClient.getFileClient(\"file.txt\");\nconst content = await snapshotFileClient.downloadToBuffer();\n```\n\n### Delete Snapshot\n\n```typescript\nawait shareClient.delete({ deleteSnapshots: \"include\" });\n```\n\n## SAS Token Generation (Node.js only)\n\n### Generate File SAS\n\n```typescript\nimport {\n  generateFileSASQueryParameters,\n  FileSASPermissions,\n  StorageSharedKeyCredential,\n} from \"@azure\u002Fstorage-file-share\";\n\nconst sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);\n\nconst sasToken = generateFileSASQueryParameters(\n  {\n    shareName: \"my-share\",\n    filePath: \"my-directory\u002Fmy-file.txt\",\n    permissions: FileSASPermissions.parse(\"r\"), \u002F\u002F read only\n    expiresOn: new Date(Date.now() + 3600 * 1000), \u002F\u002F 1 hour\n  },\n  sharedKeyCredential\n).toString();\n\nconst sasUrl = `https:\u002F\u002F${accountName}.file.core.windows.net\u002Fmy-share\u002Fmy-directory\u002Fmy-file.txt?${sasToken}`;\n```\n\n### Generate Share SAS\n\n```typescript\nimport { ShareSASPermissions, generateFileSASQueryParameters } from \"@azure\u002Fstorage-file-share\";\n\nconst sasToken = generateFileSASQueryParameters(\n  {\n    shareName: \"my-share\",\n    permissions: ShareSASPermissions.parse(\"rcwdl\"), \u002F\u002F read, create, write, delete, list\n    expiresOn: new Date(Date.now() + 24 * 3600 * 1000), \u002F\u002F 24 hours\n  },\n  sharedKeyCredential\n).toString();\n```\n\n## Error Handling\n\n```typescript\nimport { RestError } from \"@azure\u002Fstorage-file-share\";\n\ntry {\n  await shareClient.create();\n} catch (error) {\n  if (error instanceof RestError) {\n    switch (error.statusCode) {\n      case 404:\n        console.log(\"Share not found\");\n        break;\n      case 409:\n        console.log(\"Share already exists\");\n        break;\n      case 403:\n        console.log(\"Access denied\");\n        break;\n      default:\n        console.error(`Storage error ${error.statusCode}: ${error.message}`);\n    }\n  }\n  throw error;\n}\n```\n\n## TypeScript Types Reference\n\n```typescript\nimport {\n  \u002F\u002F Clients\n  ShareServiceClient,\n  ShareClient,\n  ShareDirectoryClient,\n  ShareFileClient,\n\n  \u002F\u002F Authentication\n  StorageSharedKeyCredential,\n  AnonymousCredential,\n\n  \u002F\u002F SAS\n  FileSASPermissions,\n  ShareSASPermissions,\n  AccountSASPermissions,\n  AccountSASServices,\n  AccountSASResourceTypes,\n  generateFileSASQueryParameters,\n  generateAccountSASQueryParameters,\n\n  \u002F\u002F Options & Responses\n  ShareCreateResponse,\n  FileDownloadResponseModel,\n  DirectoryItem,\n  FileItem,\n  ShareProperties,\n  FileProperties,\n\n  \u002F\u002F Errors\n  RestError,\n} from \"@azure\u002Fstorage-file-share\";\n```\n\n## Best Practices\n\n1. **Use connection strings for simplicity** — Easiest setup for development\n2. **Use DefaultAzureCredential for production** — Enable managed identity in Azure\n3. **Set quotas on shares** — Prevent unexpected storage costs\n4. **Use streaming for large files** — `uploadStream`\u002F`downloadToFile` for files > 256MB\n5. **Use ranges for partial updates** — More efficient than full file replacement\n6. **Create snapshots before major changes** — Point-in-time recovery\n7. **Handle errors gracefully** — Check `RestError.statusCode` for specific handling\n8. **Use `*IfExists` methods** — For idempotent operations\n\n## Platform Differences\n\n| Feature | Node.js | Browser |\n|---------|---------|---------|\n| `StorageSharedKeyCredential` | ✅ | ❌ |\n| `uploadFile()` | ✅ | ❌ |\n| `uploadStream()` | ✅ | ❌ |\n| `downloadToFile()` | ✅ | ❌ |\n| `downloadToBuffer()` | ✅ | ❌ |\n| SAS generation | ✅ | ❌ |\n| DefaultAzureCredential | ✅ | ❌ |\n| Anonymous\u002FSAS access | ✅ | ✅ |\n\n## When to Use\nThis skill is applicable to execute the workflow or actions described in the overview.\n","# @azure\u002Fstorage-file-share (TypeScript\u002FJavaScript)\n\nSDK for Azure File Share operations — SMB file shares, directories, and file operations.\n\n## Installation\n\n```bash\nnpm install @azure\u002Fstorage-file-share @azure\u002Fidentity\n```\n\n**Current Version**: 12.x  \n**Node.js**: >= 18.0.0\n\n## Environment Variables\n\n```bash\nAZURE_STORAGE_ACCOUNT_NAME=\u003Caccount-name>\nAZURE_STORAGE_ACCOUNT_KEY=\u003Caccount-key>\n# OR connection string\nAZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=...\n```\n\n## Authentication\n\n### Connection String (Simplest)\n\n```typescript\nimport { ShareServiceClient } from \"@azure\u002Fstorage-file-share\";\n\nconst client = ShareServiceClient.fromConnectionString(\n  process.env.AZURE_STORAGE_CONNECTION_STRING!\n);\n```\n\n### StorageSharedKeyCredential (Node.js only)\n\n```typescript\nimport { ShareServiceClient, StorageSharedKeyCredential } from \"@azure\u002Fstorage-file-share\";\n\nconst accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;\nconst accountKey = process.env.AZURE_STORAGE_ACCOUNT_KEY!;\n\nconst sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);\nconst client = new ShareServiceClient(\n  `https:\u002F\u002F${accountName}.file.core.windows.net`,\n  sharedKeyCredential\n);\n```\n\n### DefaultAzureCredential\n\n```typescript\nimport { ShareServiceClient } from \"@azure\u002Fstorage-file-share\";\nimport { DefaultAzureCredential } from \"@azure\u002Fidentity\";\n\nconst accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;\nconst client = new ShareServiceClient(\n  `https:\u002F\u002F${accountName}.file.core.windows.net`,\n  new DefaultAzureCredential()\n);\n```\n\n### SAS Token\n\n```typescript\nimport { ShareServiceClient } from \"@azure\u002Fstorage-file-share\";\n\nconst accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;\nconst sasToken = process.env.AZURE_STORAGE_SAS_TOKEN!;\n\nconst client = new ShareServiceClient(\n  `https:\u002F\u002F${accountName}.file.core.windows.net${sasToken}`\n);\n```\n\n## Client Hierarchy\n\n```\nShareServiceClient (account level)\n└── ShareClient (share level)\n    └── ShareDirectoryClient (directory level)\n        └── ShareFileClient (file level)\n```\n\n## Share Operations\n\n### Create Share\n\n```typescript\nconst shareClient = client.getShareClient(\"my-share\");\nawait shareClient.create();\n\n\u002F\u002F Create with quota (in GB)\nawait shareClient.create({ quota: 100 });\n```\n\n### List Shares\n\n```typescript\nfor await (const share of client.listShares()) {\n  console.log(share.name, share.properties.quota);\n}\n\n\u002F\u002F With prefix filter\nfor await (const share of client.listShares({ prefix: \"logs-\" })) {\n  console.log(share.name);\n}\n```\n\n### Delete Share\n\n```typescript\nawait shareClient.delete();\n\n\u002F\u002F Delete if exists\nawait shareClient.deleteIfExists();\n```\n\n### Get Share Properties\n\n```typescript\nconst properties = await shareClient.getProperties();\nconsole.log(\"Quota:\", properties.quota, \"GB\");\nconsole.log(\"Last Modified:\", properties.lastModified);\n```\n\n### Set Share Quota\n\n```typescript\nawait shareClient.setQuota(200); \u002F\u002F 200 GB\n```\n\n## Directory Operations\n\n### Create Directory\n\n```typescript\nconst directoryClient = shareClient.getDirectoryClient(\"my-directory\");\nawait directoryClient.create();\n\n\u002F\u002F Create nested directory\nconst nestedDir = shareClient.getDirectoryClient(\"parent\u002Fchild\u002Fgrandchild\");\nawait nestedDir.create();\n```\n\n### List Directories and Files\n\n```typescript\nconst directoryClient = shareClient.getDirectoryClient(\"my-directory\");\n\nfor await (const item of directoryClient.listFilesAndDirectories()) {\n  if (item.kind === \"directory\") {\n    console.log(`[DIR] ${item.name}`);\n  } else {\n    console.log(`[FILE] ${item.name} (${item.properties.contentLength} bytes)`);\n  }\n}\n```\n\n### Delete Directory\n\n```typescript\nawait directoryClient.delete();\n\n\u002F\u002F Delete if exists\nawait directoryClient.deleteIfExists();\n```\n\n### Check if Directory Exists\n\n```typescript\nconst exists = await directoryClient.exists();\nif (!exists) {\n  await directoryClient.create();\n}\n```\n\n## File Operations\n\n### Upload File (Simple)\n\n```typescript\nconst fileClient = shareClient\n  .getDirectoryClient(\"my-directory\")\n  .getFileClient(\"my-file.txt\");\n\n\u002F\u002F Upload string\nconst content = \"Hello, World!\";\nawait fileClient.create(content.length);\nawait fileClient.uploadRange(content, 0, content.length);\n```\n\n### Upload File (Node.js - from local file)\n\n```typescript\nimport * as fs from \"fs\";\nimport * as path from \"path\";\n\nconst fileClient = shareClient.rootDirectoryClient.getFileClient(\"uploaded.txt\");\nconst localFilePath = \"\u002Fpath\u002Fto\u002Flocal\u002Ffile.txt\";\nconst fileSize = fs.statSync(localFilePath).size;\n\nawait fileClient.create(fileSize);\nawait fileClient.uploadFile(localFilePath);\n```\n\n### Upload File (Buffer)\n\n```typescript\nconst buffer = Buffer.from(\"Hello, Azure Files!\");\nconst fileClient = shareClient.rootDirectoryClient.getFileClient(\"buffer-file.txt\");\n\nawait fileClient.create(buffer.length);\nawait fileClient.uploadRange(buffer, 0, buffer.length);\n```\n\n### Upload File (Stream)\n\n```typescript\nimport * as fs from \"fs\";\n\nconst fileClient = shareClient.rootDirectoryClient.getFileClient(\"streamed.txt\");\nconst readStream = fs.createReadStream(\"\u002Fpath\u002Fto\u002Flocal\u002Ffile.txt\");\nconst fileSize = fs.statSync(\"\u002Fpath\u002Fto\u002Flocal\u002Ffile.txt\").size;\n\nawait fileClient.create(fileSize);\nawait fileClient.uploadStream(readStream, fileSize, 4 * 1024 * 1024, 4); \u002F\u002F 4MB buffer, 4 concurrency\n```\n\n### Download File\n\n```typescript\nconst fileClient = shareClient\n  .getDirectoryClient(\"my-directory\")\n  .getFileClient(\"my-file.txt\");\n\nconst downloadResponse = await fileClient.download();\n\n\u002F\u002F Read as string\nconst chunks: Buffer[] = [];\nfor await (const chunk of downloadResponse.readableStreamBody!) {\n  chunks.push(Buffer.from(chunk));\n}\nconst content = Buffer.concat(chunks).toString(\"utf-8\");\n```\n\n### Download to File (Node.js)\n\n```typescript\nconst fileClient = shareClient.rootDirectoryClient.getFileClient(\"my-file.txt\");\nawait fileClient.downloadToFile(\"\u002Fpath\u002Fto\u002Flocal\u002Fdestination.txt\");\n```\n\n### Download to Buffer (Node.js)\n\n```typescript\nconst fileClient = shareClient.rootDirectoryClient.getFileClient(\"my-file.txt\");\nconst buffer = await fileClient.downloadToBuffer();\nconsole.log(buffer.toString());\n```\n\n### Delete File\n\n```typescript\nconst fileClient = shareClient.rootDirectoryClient.getFileClient(\"my-file.txt\");\nawait fileClient.delete();\n\n\u002F\u002F Delete if exists\nawait fileClient.deleteIfExists();\n```\n\n### Copy File\n\n```typescript\nconst sourceUrl = \"https:\u002F\u002Faccount.file.core.windows.net\u002Fshare\u002Fsource.txt\";\nconst destFileClient = shareClient.rootDirectoryClient.getFileClient(\"destination.txt\");\n\n\u002F\u002F Start copy operation\nconst copyPoller = await destFileClient.startCopyFromURL(sourceUrl);\nawait copyPoller.pollUntilDone();\n```\n\n## File Properties & Metadata\n\n### Get File Properties\n\n```typescript\nconst fileClient = shareClient.rootDirectoryClient.getFileClient(\"my-file.txt\");\nconst properties = await fileClient.getProperties();\n\nconsole.log(\"Content-Length:\", properties.contentLength);\nconsole.log(\"Content-Type:\", properties.contentType);\nconsole.log(\"Last Modified:\", properties.lastModified);\nconsole.log(\"ETag:\", properties.etag);\n```\n\n### Set Metadata\n\n```typescript\nawait fileClient.setMetadata({\n  author: \"John Doe\",\n  category: \"documents\",\n});\n```\n\n### Set HTTP Headers\n\n```typescript\nawait fileClient.setHttpHeaders({\n  fileContentType: \"text\u002Fplain\",\n  fileCacheControl: \"max-age=3600\",\n  fileContentDisposition: \"attachment; filename=download.txt\",\n});\n```\n\n## Range Operations\n\n### Upload Range\n\n```typescript\nconst data = Buffer.from(\"partial content\");\nawait fileClient.uploadRange(data, 100, data.length); \u002F\u002F Write at offset 100\n```\n\n### Download Range\n\n```typescript\nconst downloadResponse = await fileClient.download(100, 50); \u002F\u002F offset 100, length 50\n```\n\n### Clear Range\n\n```typescript\nawait fileClient.clearRange(0, 100); \u002F\u002F Clear first 100 bytes\n```\n\n## Snapshot Operations\n\n### Create Snapshot\n\n```typescript\nconst snapshotResponse = await shareClient.createSnapshot();\nconsole.log(\"Snapshot:\", snapshotResponse.snapshot);\n```\n\n### Access Snapshot\n\n```typescript\nconst snapshotShareClient = shareClient.withSnapshot(snapshotResponse.snapshot!);\nconst snapshotFileClient = snapshotShareClient.rootDirectoryClient.getFileClient(\"file.txt\");\nconst content = await snapshotFileClient.downloadToBuffer();\n```\n\n### Delete Snapshot\n\n```typescript\nawait shareClient.delete({ deleteSnapshots: \"include\" });\n```\n\n## SAS Token Generation (Node.js only)\n\n### Generate File SAS\n\n```typescript\nimport {\n  generateFileSASQueryParameters,\n  FileSASPermissions,\n  StorageSharedKeyCredential,\n} from \"@azure\u002Fstorage-file-share\";\n\nconst sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);\n\nconst sasToken = generateFileSASQueryParameters(\n  {\n    shareName: \"my-share\",\n    filePath: \"my-directory\u002Fmy-file.txt\",\n    permissions: FileSASPermissions.parse(\"r\"), \u002F\u002F read only\n    expiresOn: new Date(Date.now() + 3600 * 1000), \u002F\u002F 1 hour\n  },\n  sharedKeyCredential\n).toString();\n\nconst sasUrl = `https:\u002F\u002F${accountName}.file.core.windows.net\u002Fmy-share\u002Fmy-directory\u002Fmy-file.txt?${sasToken}`;\n```\n\n### Generate Share SAS\n\n```typescript\nimport { ShareSASPermissions, generateFileSASQueryParameters } from \"@azure\u002Fstorage-file-share\";\n\nconst sasToken = generateFileSASQueryParameters(\n  {\n    shareName: \"my-share\",\n    permissions: ShareSASPermissions.parse(\"rcwdl\"), \u002F\u002F read, create, write, delete, list\n    expiresOn: new Date(Date.now() + 24 * 3600 * 1000), \u002F\u002F 24 hours\n  },\n  sharedKeyCredential\n).toString();\n```\n\n## Error Handling\n\n```typescript\nimport { RestError } from \"@azure\u002Fstorage-file-share\";\n\ntry {\n  await shareClient.create();\n} catch (error) {\n  if (error instanceof RestError) {\n    switch (error.statusCode) {\n      case 404:\n        console.log(\"Share not found\");\n        break;\n      case 409:\n        console.log(\"Share already exists\");\n        break;\n      case 403:\n        console.log(\"Access denied\");\n        break;\n      default:\n        console.error(`Storage error ${error.statusCode}: ${error.message}`);\n    }\n  }\n  throw error;\n}\n```\n\n## TypeScript Types Reference\n\n```typescript\nimport {\n  \u002F\u002F Clients\n  ShareServiceClient,\n  ShareClient,\n  ShareDirectoryClient,\n  ShareFileClient,\n\n  \u002F\u002F Authentication\n  StorageSharedKeyCredential,\n  AnonymousCredential,\n\n  \u002F\u002F SAS\n  FileSASPermissions,\n  ShareSASPermissions,\n  AccountSASPermissions,\n  AccountSASServices,\n  AccountSASResourceTypes,\n  generateFileSASQueryParameters,\n  generateAccountSASQueryParameters,\n\n  \u002F\u002F Options & Responses\n  ShareCreateResponse,\n  FileDownloadResponseModel,\n  DirectoryItem,\n  FileItem,\n  ShareProperties,\n  FileProperties,\n\n  \u002F\u002F Errors\n  RestError,\n} from \"@azure\u002Fstorage-file-share\";\n```\n\n## Best Practices\n\n1. **Use connection strings for simplicity** — Easiest setup for development\n2. **Use DefaultAzureCredential for production** — Enable managed identity in Azure\n3. **Set quotas on shares** — Prevent unexpected storage costs\n4. **Use streaming for large files** — `uploadStream`\u002F`downloadToFile` for files > 256MB\n5. **Use ranges for partial updates** — More efficient than full file replacement\n6. **Create snapshots before major changes** — Point-in-time recovery\n7. **Handle errors gracefully** — Check `RestError.statusCode` for specific handling\n8. **Use `*IfExists` methods** — For idempotent operations\n\n## Platform Differences\n\n| Feature | Node.js | Browser |\n|---------|---------|---------|\n| `StorageSharedKeyCredential` | ✅ | ❌ |\n| `uploadFile()` | ✅ | ❌ |\n| `uploadStream()` | ✅ | ❌ |\n| `downloadToFile()` | ✅ | ❌ |\n| `downloadToBuffer()` | ✅ | ❌ |\n| SAS generation | ✅ | ❌ |\n| DefaultAzureCredential | ✅ | ❌ |\n| Anonymous\u002FSAS access | ✅ | ✅ |\n\n## When to Use\nThis skill is applicable to execute the workflow or actions described in the overview.\n",{"name":5,"risk":33,"source":31,"date_added":40,"description":7},"2026-02-27","main","7a38d8e7073e61c16eda85681cb32fb68a8657a5","skills-store\u002Fcopilot\u002Fazure-storage-file-share-ts","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router","https:\u002F\u002Fgithub.com\u002Fsapsapshen","2026-04-14 21:12:12",{"source":8,"skillName":5,"commands":48,"prompt":58,"zipAvailable":59},[49,52,55],{"tool":50,"command":51},"npx","npx skills add sapsapshen\u002Fai-memory-router --skill azure-storage-file-share-ts",{"tool":53,"command":54},"bunx","bunx skills add sapsapshen\u002Fai-memory-router --skill azure-storage-file-share-ts",{"tool":56,"command":57},"pnpm","pnpm dlx skills add sapsapshen\u002Fai-memory-router --skill azure-storage-file-share-ts","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fcopilot\u002Fazure-storage-file-share-ts\u002FSKILL.md",true,[],[62,86,112,122,135,154],{"skillNo":63,"name":64,"nameZh":6,"description":65,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":66,"categories":67,"keywords":73,"publishedAt":35},"01M71ATQRKG48SH06FQ697T5G9","wechat-search","Search WeChat Official Account articles using OpenClaw's web search and fetch capabilities with compliance-focused design.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fwechat-search-release\u002FSKILL.md",[68],{"categoryNo":69,"categoryName":70,"taxonomyType":71,"taxonomyTypeDesc":72},"01JBSEEDCAT000000000000037","律师与法务","PROFESSION","适用职业",[74,75,76,77,78,79,80,81,82,83,84,85],"wechat search","wechat","search","capabilities","openclaw","design","web search","compliance","web","official","fetch","with",{"skillNo":87,"name":88,"nameZh":6,"description":89,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":90,"categories":91,"keywords":92,"publishedAt":35},"01M71ATNAVGZB35PFYM2GC5N00","trend-tap","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend tap', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-tap\u002FSKILL.md",[],[93,94,95,96,97,98,76,99,100,101,102,103,104,105,106,107,108,109,110,111],"trend","trend tap","tap","api keys","Bash","time","trending","hacker","aggregator","do","when","brew","live","data","google","install","read","across","api",{"skillNo":113,"name":114,"nameZh":6,"description":115,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":116,"categories":117,"keywords":118,"publishedAt":35},"01M71ATJ9AM5KM15AA8PS302EB","trend-radar","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend pulse', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-radar\u002FSKILL.md",[],[119,120,93,104,105,106,107,97,76,109,121,110,111,103,101,100,99,108,98,96],"trend radar","radar","pulse",{"skillNo":123,"name":124,"nameZh":6,"description":125,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":128,"publishedAt":35},"01M71ATGF095N3EJM9G8SD0BB5","tech-news-daily","每日科技新闻汇——从全球多个 RSS 源抓取最新科技新闻，翻译（英→中）、去重、排版成每日简报。当用户询问科技新闻、科技新鲜事、每日科技、技术动态、Daily Tech News 或类似表达时触发此技能。","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftech-news-daily\u002FSKILL.md",[],[129,130,131,132,133,134],"news","tech","tech news daily","daily","rss","翻译",{"skillNo":136,"name":137,"nameZh":6,"description":138,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":139,"categories":140,"keywords":146,"publishedAt":35},"01M71ATFAEAMQ17M70NQNY7SR8","summarize","Summarize URLs or files with the summarize CLI (web, PDFs, images, audio, YouTube).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsummarize\u002FSKILL.md",[141],{"categoryNo":142,"categoryName":143,"taxonomyType":144,"taxonomyTypeDesc":145},"01JBSEEDCAT000000000000021","资料检索与研究","SCENARIO","使用场景",[137,82,147,148,149,85,104,150,151,152,95,153,108],"Audio","cli","youtube","images","https","files","pdfs",{"skillNo":155,"name":156,"nameZh":6,"description":157,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":158,"categories":159,"keywords":160,"publishedAt":35},"01M71ATDNS3R0M4H936PACQAWZ","sonoscli","Control Sonos speakers (discover\u002Fstatus\u002Fplay\u002Fvolume\u002Fgroup).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsonoscli\u002FSKILL.md",[],[156,161,162,163,108,164,151,165,166,167,168,169],"status","play","go","latest","github","discover","control","cmd","volume"]