-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Storage] Async iterator for listing blobs and containers - storage-blob #3136
Changes from 12 commits
9524d20
eecb12a
28e8773
dc03069
bb41616
da1afa5
34e3772
eb3b1ca
72cd066
7d7cb2f
7922584
d1cf6d0
c8128b5
49c1da6
c272c6a
5b07b44
cdd3d2e
43d30c0
bc932b3
3fb743a
842de33
d7b7f71
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* | ||
Setup: Enter your storage account name and shared key in main() | ||
*/ | ||
|
||
import { | ||
ContainerClient, | ||
BlobServiceClient, | ||
StorageClient, | ||
SharedKeyCredential, | ||
BlobClient, | ||
BlockBlobClient | ||
} from "../../src"; // Change to "@azure/storage-blob" in your package | ||
|
||
async function main() { | ||
// Enter your storage account name and shared key | ||
const account = ""; | ||
const accountKey = ""; | ||
|
||
// Use SharedKeyCredential with storage account and account key | ||
const sharedKeyCredential = new SharedKeyCredential(account, accountKey); | ||
|
||
// Use sharedKeyCredential, tokenCredential or anonymousCredential to create a pipeline | ||
const pipeline = StorageClient.newPipeline(sharedKeyCredential); | ||
|
||
// List containers | ||
const blobServiceClient = new BlobServiceClient( | ||
// When using AnonymousCredential, following url should include a valid SAS or support public access | ||
`https://${account}.blob.core.windows.net`, | ||
pipeline | ||
); | ||
|
||
// List Containers | ||
let iter1 = await blobServiceClient.listContainers(); | ||
let i = 1; | ||
for await (const container of iter1) { | ||
console.log(`Container ${i++}: ${container.name}`); | ||
} | ||
|
||
// List containers - generator syntax | ||
let iter2 = await blobServiceClient.listContainers(); | ||
i = 1; | ||
let containerItem = await iter2.next(); | ||
do { | ||
console.log(`Container ${i++}: ${containerItem.value.name}`); | ||
containerItem = await iter2.next(); | ||
} while (containerItem.value); | ||
|
||
// Create a container | ||
const containerName = `newcontainer${new Date().getTime()}`; | ||
const containerClient = ContainerClient.fromBlobServiceClient(blobServiceClient, containerName); | ||
|
||
const createContainerResponse = await containerClient.create(); | ||
console.log(`Created container ${containerName} successfully`, createContainerResponse.requestId); | ||
|
||
for (let index = 0; index < 4; index++) { | ||
// Create a blob | ||
let content = "hello"; | ||
let blobName = "newblob" + new Date().getTime(); | ||
let blobClient = BlobClient.fromContainerClient(containerClient, blobName); | ||
let blockBlobClient = BlockBlobClient.fromBlobClient(blobClient); | ||
let uploadBlobResponse = await blockBlobClient.upload(content, content.length); | ||
console.log(`Uploaded block blob ${blobName} successfully`, uploadBlobResponse.requestId); | ||
} | ||
|
||
// List blobs | ||
iter1 = await containerClient.listBlobs(); | ||
i = 1; | ||
for await (const blob of iter1) { | ||
console.log(`Blob ${i++}: ${blob.name}`); | ||
} | ||
|
||
// List blobs - generator syntax | ||
iter2 = await containerClient.listBlobs(); | ||
i = 1; | ||
let blobItem = await iter2.next(); | ||
do { | ||
console.log(`Blob ${i++}: ${blobItem.value.name}`); | ||
blobItem = await iter2.next(); | ||
} while (blobItem.value); | ||
} | ||
|
||
// An async method returns a Promise object, which is compatible with then().catch() coding style. | ||
main() | ||
.then(() => { | ||
console.log("Successfully executed the sample."); | ||
}) | ||
.catch((err) => { | ||
console.log(err.message); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -548,6 +548,53 @@ export class ContainerClient extends StorageClient { | |
}); | ||
} | ||
|
||
/** | ||
* Iterates over blobs under the specified container. | ||
* | ||
* @param {ContainerListBlobsSegmentOptions} [options={}] Options to list blobs(optional) | ||
* @returns {AsyncIterableIterator<Models.BlobItem>} | ||
* @memberof ContainerClient | ||
* | ||
* @example | ||
* for await (const blob of containerClient.listBlobs()) { | ||
* console.log(`Container: ${blob.name}`); | ||
* } | ||
* | ||
* @example | ||
* let iter1 = containerClient.listBlobs(); | ||
* let i = 1; | ||
* for await (const blob of iter1) { | ||
* console.log(`${i}: ${blob.name}`); | ||
* i++; | ||
* } | ||
* | ||
* @example | ||
* let iter2 = await containerClient.listBlobs(); | ||
* i = 1; | ||
* let blobItem = await iter2.next(); | ||
* do { | ||
* console.log(`Blob ${i++}: ${blobItem.value.name}`); | ||
* blobItem = await iter2.next(); | ||
* } while (blobItem.value); | ||
* | ||
*/ | ||
public async *listBlobs( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or called There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated |
||
options: ContainerListBlobsSegmentOptions = {} | ||
): AsyncIterableIterator<Models.BlobItem> { | ||
let marker = undefined; | ||
const containerClient = this; | ||
const aborter = !options.abortSignal ? Aborter.none : options.abortSignal; | ||
let listBlobsResponse; | ||
do { | ||
listBlobsResponse = await containerClient.listBlobFlatSegment(marker, { | ||
...options, | ||
abortSignal: aborter | ||
}); | ||
marker = listBlobsResponse.nextMarker; | ||
yield* listBlobsResponse.segment.blobItems; | ||
} while (marker); | ||
} | ||
|
||
/** | ||
* listBlobFlatSegment returns a single segment of blobs starting from the | ||
* specified Marker. Use an empty Marker to start enumeration from the beginning. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering what will happen if Aborter aborted iteration
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Example -
[ About 6500 containers are present in the account ]
The request was aborted
.[ X = 10000 yielded the same result ]
The request was aborted
is printed in the terminal.