UNPKG

@azure/storage-blob

Version:
1,144 lines • 138 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var Clients_exports = {}; __export(Clients_exports, { AppendBlobClient: () => AppendBlobClient, BlobClient: () => BlobClient, BlockBlobClient: () => BlockBlobClient, PageBlobClient: () => PageBlobClient }); module.exports = __toCommonJS(Clients_exports); var import_core_rest_pipeline = require("@azure/core-rest-pipeline"); var import_core_auth = require("@azure/core-auth"); var import_core_util = require("@azure/core-util"); var import_core_util2 = require("@azure/core-util"); var import_BlobDownloadResponse = require("./BlobDownloadResponse.js"); var import_BlobQueryResponse = require("./BlobQueryResponse.js"); var import_storage_common = require("@azure/storage-common"); var import_models = require("./models.js"); var import_PageBlobRangeResponse = require("./PageBlobRangeResponse.js"); var import_Pipeline = require("./Pipeline.js"); var import_BlobStartCopyFromUrlPoller = require("./pollers/BlobStartCopyFromUrlPoller.js"); var import_Range = require("./Range.js"); var import_StorageClient = require("./StorageClient.js"); var import_Batch = require("./utils/Batch.js"); var import_storage_common2 = require("@azure/storage-common"); var import_constants = require("./utils/constants.js"); var import_tracing = require("./utils/tracing.js"); var import_utils_common = require("./utils/utils.common.js"); var import_utils = require("./utils/utils.js"); var import_BlobSASSignatureValues = require("./sas/BlobSASSignatureValues.js"); var import_BlobLeaseClient = require("./BlobLeaseClient.js"); class BlobClient extends import_StorageClient.StorageClient { /** * blobContext provided by protocol layer. */ blobContext; _name; _containerName; _versionId; _snapshot; /** * Config used in creating blob client instances. */ blobClientConfig; /** * The name of the blob. */ get name() { return this._name; } /** * The name of the storage container the blob is associated with. */ get containerName() { return this._containerName; } constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, options) { options = options || {}; let pipeline; let url; if ((0, import_Pipeline.isPipelineLike)(credentialOrPipelineOrContainerName)) { url = urlOrConnectionString; pipeline = credentialOrPipelineOrContainerName; options = blobNameOrOptions; } else if (import_core_util.isNodeLike && credentialOrPipelineOrContainerName instanceof import_storage_common.StorageSharedKeyCredential || credentialOrPipelineOrContainerName instanceof import_storage_common.AnonymousCredential || (0, import_core_auth.isTokenCredential)(credentialOrPipelineOrContainerName)) { url = urlOrConnectionString; options = blobNameOrOptions; pipeline = (0, import_Pipeline.newPipeline)(credentialOrPipelineOrContainerName, options); } else if (!credentialOrPipelineOrContainerName && typeof credentialOrPipelineOrContainerName !== "string") { url = urlOrConnectionString; if (blobNameOrOptions && typeof blobNameOrOptions !== "string") { options = blobNameOrOptions; } pipeline = (0, import_Pipeline.newPipeline)(new import_storage_common.AnonymousCredential(), options); } else if (credentialOrPipelineOrContainerName && typeof credentialOrPipelineOrContainerName === "string" && blobNameOrOptions && typeof blobNameOrOptions === "string") { const containerName = credentialOrPipelineOrContainerName; const blobName = blobNameOrOptions; const extractedCreds = (0, import_utils_common.extractConnectionStringParts)(urlOrConnectionString); if (extractedCreds.kind === "AccountConnString") { if (import_core_util.isNodeLike) { const sharedKeyCredential = new import_storage_common.StorageSharedKeyCredential( extractedCreds.accountName, extractedCreds.accountKey ); url = (0, import_utils_common.appendToURLPath)( (0, import_utils_common.appendToURLPath)(extractedCreds.url, encodeURIComponent(containerName)), encodeURIComponent(blobName) ); if (!options.proxyOptions) { options.proxyOptions = (0, import_core_rest_pipeline.getDefaultProxySettings)(extractedCreds.proxyUri); } pipeline = (0, import_Pipeline.newPipeline)(sharedKeyCredential, options); } else { throw new Error("Account connection string is only supported in Node.js environment"); } } else if (extractedCreds.kind === "SASConnString") { url = (0, import_utils_common.appendToURLPath)( (0, import_utils_common.appendToURLPath)(extractedCreds.url, encodeURIComponent(containerName)), encodeURIComponent(blobName) ) + "?" + extractedCreds.accountSas; pipeline = (0, import_Pipeline.newPipeline)(new import_storage_common.AnonymousCredential(), options); } else { throw new Error( "Connection string must be either an Account connection string or a SAS connection string" ); } } else { throw new Error("Expecting non-empty strings for containerName and blobName parameters"); } super(url, pipeline); ({ blobName: this._name, containerName: this._containerName } = this.getBlobAndContainerNamesFromUrl()); this.blobContext = this.storageClientContext.blob; this._snapshot = (0, import_utils_common.getURLParameter)(this.url, import_constants.URLConstants.Parameters.SNAPSHOT); this._versionId = (0, import_utils_common.getURLParameter)(this.url, import_constants.URLConstants.Parameters.VERSIONID); this.blobClientConfig = options; } /** * Creates a new BlobClient object identical to the source but with the specified snapshot timestamp. * Provide "" will remove the snapshot and return a Client to the base blob. * * @param snapshot - The snapshot timestamp. * @returns A new BlobClient object identical to the source but with the specified snapshot timestamp */ withSnapshot(snapshot) { return new BlobClient( (0, import_utils_common.setURLParameter)( this.url, import_constants.URLConstants.Parameters.SNAPSHOT, snapshot.length === 0 ? void 0 : snapshot ), this.pipeline, this.blobClientConfig ); } /** * Creates a new BlobClient object pointing to a version of this blob. * Provide "" will remove the versionId and return a Client to the base blob. * * @param versionId - The versionId. * @returns A new BlobClient object pointing to the version of this blob. */ withVersion(versionId) { return new BlobClient( (0, import_utils_common.setURLParameter)( this.url, import_constants.URLConstants.Parameters.VERSIONID, versionId.length === 0 ? void 0 : versionId ), this.pipeline, this.blobClientConfig ); } /** * Creates a AppendBlobClient object. * */ getAppendBlobClient() { return new AppendBlobClient(this.url, this.pipeline, this.blobClientConfig); } /** * Creates a BlockBlobClient object. * */ getBlockBlobClient() { return new BlockBlobClient(this.url, this.pipeline, this.blobClientConfig); } /** * Creates a PageBlobClient object. * */ getPageBlobClient() { return new PageBlobClient(this.url, this.pipeline, this.blobClientConfig); } /** * Reads or downloads a blob from the system, including its metadata and properties. * You can also call Get Blob to read a snapshot. * * * In Node.js, data returns in a Readable stream readableStreamBody * * In browsers, data returns in a promise blobBody * * @see https://learn.microsoft.com/rest/api/storageservices/get-blob * * @param offset - From which position of the blob to download, greater than or equal to 0 * @param count - How much data to be downloaded, greater than 0. Will download to the end when undefined * @param options - Optional options to Blob Download operation. * * * Example usage (Node.js): * * ```ts snippet:ReadmeSampleDownloadBlob_Node * import { BlobServiceClient } from "@azure/storage-blob"; * import { DefaultAzureCredential } from "@azure/identity"; * * const account = "<account>"; * const blobServiceClient = new BlobServiceClient( * `https://${account}.blob.core.windows.net`, * new DefaultAzureCredential(), * ); * * const containerName = "<container name>"; * const blobName = "<blob name>"; * const containerClient = blobServiceClient.getContainerClient(containerName); * const blobClient = containerClient.getBlobClient(blobName); * * // Get blob content from position 0 to the end * // In Node.js, get downloaded data by accessing downloadBlockBlobResponse.readableStreamBody * const downloadBlockBlobResponse = await blobClient.download(); * if (downloadBlockBlobResponse.readableStreamBody) { * const downloaded = await streamToString(downloadBlockBlobResponse.readableStreamBody); * console.log(`Downloaded blob content: ${downloaded}`); * } * * async function streamToString(stream: NodeJS.ReadableStream): Promise<string> { * const result = await new Promise<Buffer<ArrayBuffer>>((resolve, reject) => { * const chunks: Buffer[] = []; * stream.on("data", (data) => { * chunks.push(Buffer.isBuffer(data) ? data : Buffer.from(data)); * }); * stream.on("end", () => { * resolve(Buffer.concat(chunks)); * }); * stream.on("error", reject); * }); * return result.toString(); * } * ``` * * Example usage (browser): * * ```ts snippet:ReadmeSampleDownloadBlob_Browser * import { BlobServiceClient } from "@azure/storage-blob"; * import { DefaultAzureCredential } from "@azure/identity"; * * const account = "<account>"; * const blobServiceClient = new BlobServiceClient( * `https://${account}.blob.core.windows.net`, * new DefaultAzureCredential(), * ); * * const containerName = "<container name>"; * const blobName = "<blob name>"; * const containerClient = blobServiceClient.getContainerClient(containerName); * const blobClient = containerClient.getBlobClient(blobName); * * // Get blob content from position 0 to the end * // In browsers, get downloaded data by accessing downloadBlockBlobResponse.blobBody * const downloadBlockBlobResponse = await blobClient.download(); * const blobBody = await downloadBlockBlobResponse.blobBody; * if (blobBody) { * const downloaded = await blobBody.text(); * console.log(`Downloaded blob content: ${downloaded}`); * } * ``` */ async download(offset = 0, count, options = {}) { options.conditions = options.conditions || {}; options.conditions = options.conditions || {}; (0, import_models.ensureCpkIfSpecified)(options.customerProvidedKey, this.isHttps); return import_tracing.tracingClient.withSpan("BlobClient-download", options, async (updatedOptions) => { let contentChecksumAlgorithm = options.contentChecksumAlgorithm ?? this.blobClientConfig?.downloadContentChecksumAlgorithm; if (contentChecksumAlgorithm === void 0) { contentChecksumAlgorithm = "Customized"; } else if (contentChecksumAlgorithm === "Auto") { contentChecksumAlgorithm = "StorageCrc64"; } if (contentChecksumAlgorithm === "StorageCrc64") { await import_storage_common2.StorageCRC64Calculator.init(); } const res = (0, import_utils_common.assertResponse)( await this.blobContext.download({ abortSignal: options.abortSignal, leaseAccessConditions: options.conditions, modifiedAccessConditions: { ...options.conditions, ifTags: options.conditions?.tagConditions }, requestOptions: { onDownloadProgress: import_core_util.isNodeLike ? void 0 : options.onProgress // for Node.js, progress is reported by RetriableReadableStream }, range: offset === 0 && !count ? void 0 : (0, import_Range.rangeToString)({ offset, count }), rangeGetContentMD5: options.rangeGetContentMD5, rangeGetContentCRC64: options.rangeGetContentCrc64, snapshot: options.snapshot, cpkInfo: options.customerProvidedKey, tracingOptions: updatedOptions.tracingOptions, structuredBodyType: contentChecksumAlgorithm === "StorageCrc64" ? "XSM/1.0; properties=crc64" : void 0 }) ); const wrappedRes = { ...res, _response: res._response, // _response is made non-enumerable objectReplicationDestinationPolicyId: res.objectReplicationPolicyId, objectReplicationSourceProperties: (0, import_utils_common.parseObjectReplicationRecord)(res.objectReplicationRules) }; if (!import_core_util.isNodeLike) { if (contentChecksumAlgorithm === "StorageCrc64") { wrappedRes.blobBody = (0, import_storage_common2.structuredMessageDecodingBrowser)(await wrappedRes.blobBody); } return wrappedRes; } if (options.maxRetryRequests === void 0 || options.maxRetryRequests < 0) { options.maxRetryRequests = import_constants.DEFAULT_MAX_DOWNLOAD_RETRY_REQUESTS; } if (res.contentLength === void 0) { throw new RangeError(`File download response doesn't contain valid content length header`); } if (contentChecksumAlgorithm === "StorageCrc64" && res.structuredContentLength === void 0) { throw new RangeError(`Unexpected structured content length`); } if (!res.etag) { throw new RangeError(`File download response doesn't contain valid etag header`); } const expectedContentLength = contentChecksumAlgorithm === "StorageCrc64" ? res.structuredContentLength : res.contentLength; return new import_BlobDownloadResponse.BlobDownloadResponse( wrappedRes, async (start) => { const updatedDownloadOptions = { leaseAccessConditions: options.conditions, modifiedAccessConditions: { ifMatch: options.conditions.ifMatch || res.etag, ifModifiedSince: options.conditions.ifModifiedSince, ifNoneMatch: options.conditions.ifNoneMatch, ifUnmodifiedSince: options.conditions.ifUnmodifiedSince, ifTags: options.conditions?.tagConditions }, range: (0, import_Range.rangeToString)({ count: offset + expectedContentLength - start, offset: start }), rangeGetContentMD5: options.rangeGetContentMD5, rangeGetContentCRC64: options.rangeGetContentCrc64, snapshot: options.snapshot, cpkInfo: options.customerProvidedKey, structuredBodyType: contentChecksumAlgorithm === "StorageCrc64" ? "XSM/1.0; properties=crc64" : void 0 }; const resBody = (await this.blobContext.download({ abortSignal: options.abortSignal, ...updatedDownloadOptions })).readableStreamBody; if (contentChecksumAlgorithm === "StorageCrc64") { return (0, import_storage_common.structuredMessageDecodingStream)(resBody, {}); } else { return resBody; } }, offset, expectedContentLength, { maxRetryRequests: options.maxRetryRequests, onProgress: options.onProgress } ); }); } /** * Returns true if the Azure blob resource represented by this client exists; false otherwise. * * NOTE: use this function with care since an existing blob might be deleted by other clients or * applications. Vice versa new blobs might be added by other clients or applications after this * function completes. * * @param options - options to Exists operation. */ async exists(options = {}) { return import_tracing.tracingClient.withSpan("BlobClient-exists", options, async (updatedOptions) => { try { (0, import_models.ensureCpkIfSpecified)(options.customerProvidedKey, this.isHttps); await this.getProperties({ abortSignal: options.abortSignal, customerProvidedKey: options.customerProvidedKey, conditions: options.conditions, tracingOptions: updatedOptions.tracingOptions }); return true; } catch (e) { if (e.statusCode === 404) { return false; } else if (e.statusCode === 409 && (e.details.errorCode === import_constants.BlobUsesCustomerSpecifiedEncryptionMsg || e.details.errorCode === import_constants.BlobDoesNotUseCustomerSpecifiedEncryption)) { return true; } throw e; } }); } /** * Returns all user-defined metadata, standard HTTP properties, and system properties * for the blob. It does not return the content of the blob. * @see https://learn.microsoft.com/rest/api/storageservices/get-blob-properties * * WARNING: The `metadata` object returned in the response will have its keys in lowercase, even if * they originally contained uppercase characters. This differs from the metadata keys returned by * the methods of {@link ContainerClient} that list blobs using the `includeMetadata` option, which * will retain their original casing. * * @param options - Optional options to Get Properties operation. */ async getProperties(options = {}) { options.conditions = options.conditions || {}; (0, import_models.ensureCpkIfSpecified)(options.customerProvidedKey, this.isHttps); return import_tracing.tracingClient.withSpan("BlobClient-getProperties", options, async (updatedOptions) => { const res = (0, import_utils_common.assertResponse)( await this.blobContext.getProperties({ abortSignal: options.abortSignal, leaseAccessConditions: options.conditions, modifiedAccessConditions: { ...options.conditions, ifTags: options.conditions?.tagConditions }, cpkInfo: options.customerProvidedKey, tracingOptions: updatedOptions.tracingOptions }) ); return { ...res, _response: res._response, // _response is made non-enumerable objectReplicationDestinationPolicyId: res.objectReplicationPolicyId, objectReplicationSourceProperties: (0, import_utils_common.parseObjectReplicationRecord)(res.objectReplicationRules) }; }); } /** * Marks the specified blob or snapshot for deletion. The blob is later deleted * during garbage collection. Note that in order to delete a blob, you must delete * all of its snapshots. You can delete both at the same time with the Delete * Blob operation. * @see https://learn.microsoft.com/rest/api/storageservices/delete-blob * * @param options - Optional options to Blob Delete operation. */ async delete(options = {}) { options.conditions = options.conditions || {}; return import_tracing.tracingClient.withSpan("BlobClient-delete", options, async (updatedOptions) => { return (0, import_utils_common.assertResponse)( await this.blobContext.delete({ abortSignal: options.abortSignal, deleteSnapshots: options.deleteSnapshots, leaseAccessConditions: options.conditions, modifiedAccessConditions: { ...options.conditions, ifTags: options.conditions?.tagConditions }, tracingOptions: updatedOptions.tracingOptions, accessTierIfModifiedSince: options.conditions?.accessTierIfModifiedSince, accessTierIfUnmodifiedSince: options.conditions?.accessTierIfUnmodifiedSince }) ); }); } /** * Marks the specified blob or snapshot for deletion if it exists. The blob is later deleted * during garbage collection. Note that in order to delete a blob, you must delete * all of its snapshots. You can delete both at the same time with the Delete * Blob operation. * @see https://learn.microsoft.com/rest/api/storageservices/delete-blob * * @param options - Optional options to Blob Delete operation. */ async deleteIfExists(options = {}) { return import_tracing.tracingClient.withSpan("BlobClient-deleteIfExists", options, async (updatedOptions) => { try { const res = (0, import_utils_common.assertResponse)(await this.delete(updatedOptions)); return { succeeded: true, ...res, _response: res._response // _response is made non-enumerable }; } catch (e) { if (e.details?.errorCode === "BlobNotFound") { return { succeeded: false, ...e.response?.parsedHeaders, _response: e.response }; } throw e; } }); } /** * Restores the contents and metadata of soft deleted blob and any associated * soft deleted snapshots. Undelete Blob is supported only on version 2017-07-29 * or later. * @see https://learn.microsoft.com/rest/api/storageservices/undelete-blob * * @param options - Optional options to Blob Undelete operation. */ async undelete(options = {}) { return import_tracing.tracingClient.withSpan("BlobClient-undelete", options, async (updatedOptions) => { return (0, import_utils_common.assertResponse)( await this.blobContext.undelete({ abortSignal: options.abortSignal, tracingOptions: updatedOptions.tracingOptions }) ); }); } /** * Sets system properties on the blob. * * If no value provided, or no value provided for the specified blob HTTP headers, * these blob HTTP headers without a value will be cleared. * @see https://learn.microsoft.com/rest/api/storageservices/set-blob-properties * * @param blobHTTPHeaders - If no value provided, or no value provided for * the specified blob HTTP headers, these blob HTTP * headers without a value will be cleared. * A common header to set is `blobContentType` * enabling the browser to provide functionality * based on file type. * @param options - Optional options to Blob Set HTTP Headers operation. */ async setHTTPHeaders(blobHTTPHeaders, options = {}) { options.conditions = options.conditions || {}; (0, import_models.ensureCpkIfSpecified)(options.customerProvidedKey, this.isHttps); return import_tracing.tracingClient.withSpan("BlobClient-setHTTPHeaders", options, async (updatedOptions) => { return (0, import_utils_common.assertResponse)( await this.blobContext.setHttpHeaders({ abortSignal: options.abortSignal, blobHttpHeaders: blobHTTPHeaders, leaseAccessConditions: options.conditions, modifiedAccessConditions: { ...options.conditions, ifTags: options.conditions?.tagConditions }, // cpkInfo: options.customerProvidedKey, // CPK is not included in Swagger, should change this back when this issue is fixed in Swagger. tracingOptions: updatedOptions.tracingOptions }) ); }); } /** * Sets user-defined metadata for the specified blob as one or more name-value pairs. * * If no option provided, or no metadata defined in the parameter, the blob * metadata will be removed. * @see https://learn.microsoft.com/rest/api/storageservices/set-blob-metadata * * @param metadata - Replace existing metadata with this value. * If no value provided the existing metadata will be removed. * @param options - Optional options to Set Metadata operation. */ async setMetadata(metadata, options = {}) { options.conditions = options.conditions || {}; (0, import_models.ensureCpkIfSpecified)(options.customerProvidedKey, this.isHttps); return import_tracing.tracingClient.withSpan("BlobClient-setMetadata", options, async (updatedOptions) => { return (0, import_utils_common.assertResponse)( await this.blobContext.setMetadata({ abortSignal: options.abortSignal, leaseAccessConditions: options.conditions, metadata, modifiedAccessConditions: { ...options.conditions, ifTags: options.conditions?.tagConditions }, cpkInfo: options.customerProvidedKey, encryptionScope: options.encryptionScope, tracingOptions: updatedOptions.tracingOptions }) ); }); } /** * Sets tags on the underlying blob. * A blob can have up to 10 tags. Tag keys must be between 1 and 128 characters. Tag values must be between 0 and 256 characters. * Valid tag key and value characters include lower and upper case letters, digits (0-9), * space (' '), plus ('+'), minus ('-'), period ('.'), foward slash ('/'), colon (':'), equals ('='), and underscore ('_'). * * @param tags - * @param options - */ async setTags(tags, options = {}) { return import_tracing.tracingClient.withSpan("BlobClient-setTags", options, async (updatedOptions) => { return (0, import_utils_common.assertResponse)( await this.blobContext.setTags({ abortSignal: options.abortSignal, leaseAccessConditions: options.conditions, modifiedAccessConditions: { ...options.conditions, ifTags: options.conditions?.tagConditions }, blobModifiedAccessConditions: options.conditions, tracingOptions: updatedOptions.tracingOptions, tags: (0, import_utils_common.toBlobTags)(tags) }) ); }); } /** * Gets the tags associated with the underlying blob. * * @param options - */ async getTags(options = {}) { return import_tracing.tracingClient.withSpan("BlobClient-getTags", options, async (updatedOptions) => { const response = (0, import_utils_common.assertResponse)( await this.blobContext.getTags({ abortSignal: options.abortSignal, leaseAccessConditions: options.conditions, modifiedAccessConditions: { ...options.conditions, ifTags: options.conditions?.tagConditions }, blobModifiedAccessConditions: options.conditions, tracingOptions: updatedOptions.tracingOptions }) ); const wrappedResponse = { ...response, _response: response._response, // _response is made non-enumerable tags: (0, import_utils_common.toTags)({ blobTagSet: response.blobTagSet }) || {} }; return wrappedResponse; }); } /** * Get a {@link BlobLeaseClient} that manages leases on the blob. * * @param proposeLeaseId - Initial proposed lease Id. * @returns A new BlobLeaseClient object for managing leases on the blob. */ getBlobLeaseClient(proposeLeaseId) { return new import_BlobLeaseClient.BlobLeaseClient(this, proposeLeaseId); } /** * Creates a read-only snapshot of a blob. * @see https://learn.microsoft.com/rest/api/storageservices/snapshot-blob * * @param options - Optional options to the Blob Create Snapshot operation. */ async createSnapshot(options = {}) { options.conditions = options.conditions || {}; (0, import_models.ensureCpkIfSpecified)(options.customerProvidedKey, this.isHttps); return import_tracing.tracingClient.withSpan("BlobClient-createSnapshot", options, async (updatedOptions) => { return (0, import_utils_common.assertResponse)( await this.blobContext.createSnapshot({ abortSignal: options.abortSignal, leaseAccessConditions: options.conditions, metadata: options.metadata, modifiedAccessConditions: { ...options.conditions, ifTags: options.conditions?.tagConditions }, cpkInfo: options.customerProvidedKey, encryptionScope: options.encryptionScope, tracingOptions: updatedOptions.tracingOptions }) ); }); } /** * Asynchronously copies a blob to a destination within the storage account. * This method returns a long running operation poller that allows you to wait * indefinitely until the copy is completed. * You can also cancel a copy before it is completed by calling `cancelOperation` on the poller. * Note that the onProgress callback will not be invoked if the operation completes in the first * request, and attempting to cancel a completed copy will result in an error being thrown. * * In version 2012-02-12 and later, the source for a Copy Blob operation can be * a committed blob in any Azure storage account. * Beginning with version 2015-02-21, the source for a Copy Blob operation can be * an Azure file in any Azure storage account. * Only storage accounts created on or after June 7th, 2012 allow the Copy Blob * operation to copy from another storage account. * @see https://learn.microsoft.com/rest/api/storageservices/copy-blob * * ```ts snippet:ClientsBeginCopyFromURL * import { BlobServiceClient } from "@azure/storage-blob"; * import { DefaultAzureCredential } from "@azure/identity"; * * const account = "<account>"; * const blobServiceClient = new BlobServiceClient( * `https://${account}.blob.core.windows.net`, * new DefaultAzureCredential(), * ); * * const containerName = "<container name>"; * const blobName = "<blob name>"; * const containerClient = blobServiceClient.getContainerClient(containerName); * const blobClient = containerClient.getBlobClient(blobName); * * // Example using automatic polling * const automaticCopyPoller = await blobClient.beginCopyFromURL("url"); * const automaticResult = await automaticCopyPoller.pollUntilDone(); * * // Example using manual polling * const manualCopyPoller = await blobClient.beginCopyFromURL("url"); * while (!manualCopyPoller.isDone()) { * await manualCopyPoller.poll(); * } * const manualResult = manualCopyPoller.getResult(); * * // Example using progress updates * const progressUpdatesCopyPoller = await blobClient.beginCopyFromURL("url", { * onProgress(state) { * console.log(`Progress: ${state.copyProgress}`); * }, * }); * const progressUpdatesResult = await progressUpdatesCopyPoller.pollUntilDone(); * * // Example using a changing polling interval (default 15 seconds) * const pollingIntervalCopyPoller = await blobClient.beginCopyFromURL("url", { * intervalInMs: 1000, // poll blob every 1 second for copy progress * }); * const pollingIntervalResult = await pollingIntervalCopyPoller.pollUntilDone(); * * // Example using copy cancellation: * const cancelCopyPoller = await blobClient.beginCopyFromURL("url"); * // cancel operation after starting it. * try { * await cancelCopyPoller.cancelOperation(); * // calls to get the result now throw PollerCancelledError * cancelCopyPoller.getResult(); * } catch (err: any) { * if (err.name === "PollerCancelledError") { * console.log("The copy was cancelled."); * } * } * ``` * * @param copySource - url to the source Azure Blob/File. * @param options - Optional options to the Blob Start Copy From URL operation. */ async beginCopyFromURL(copySource, options = {}) { const client = { abortCopyFromURL: (...args) => this.abortCopyFromURL(...args), getProperties: (...args) => this.getProperties(...args), startCopyFromURL: (...args) => this.startCopyFromURL(...args) }; const poller = new import_BlobStartCopyFromUrlPoller.BlobBeginCopyFromUrlPoller({ blobClient: client, copySource, intervalInMs: options.intervalInMs, onProgress: options.onProgress, resumeFrom: options.resumeFrom, startCopyFromURLOptions: options }); await poller.poll(); return poller; } /** * Aborts a pending asynchronous Copy Blob operation, and leaves a destination blob with zero * length and full metadata. Version 2012-02-12 and newer. * @see https://learn.microsoft.com/rest/api/storageservices/abort-copy-blob * * @param copyId - Id of the Copy From URL operation. * @param options - Optional options to the Blob Abort Copy From URL operation. */ async abortCopyFromURL(copyId, options = {}) { return import_tracing.tracingClient.withSpan( "BlobClient-abortCopyFromURL", options, async (updatedOptions) => { return (0, import_utils_common.assertResponse)( await this.blobContext.abortCopyFromURL(copyId, { abortSignal: options.abortSignal, leaseAccessConditions: options.conditions, tracingOptions: updatedOptions.tracingOptions }) ); } ); } /** * The synchronous Copy From URL operation copies a blob or an internet resource to a new blob. It will not * return a response until the copy is complete. * @see https://learn.microsoft.com/rest/api/storageservices/copy-blob-from-url * * @param copySource - The source URL to copy from, Shared Access Signature(SAS) maybe needed for authentication * @param options - */ async syncCopyFromURL(copySource, options = {}) { options.conditions = options.conditions || {}; options.sourceConditions = options.sourceConditions || {}; return import_tracing.tracingClient.withSpan("BlobClient-syncCopyFromURL", options, async (updatedOptions) => { return (0, import_utils_common.assertResponse)( await this.blobContext.copyFromURL(copySource, { abortSignal: options.abortSignal, metadata: options.metadata, leaseAccessConditions: options.conditions, modifiedAccessConditions: { ...options.conditions, ifTags: options.conditions?.tagConditions }, sourceModifiedAccessConditions: { sourceIfMatch: options.sourceConditions?.ifMatch, sourceIfModifiedSince: options.sourceConditions?.ifModifiedSince, sourceIfNoneMatch: options.sourceConditions?.ifNoneMatch, sourceIfUnmodifiedSince: options.sourceConditions?.ifUnmodifiedSince }, sourceContentMD5: options.sourceContentMD5, copySourceAuthorization: (0, import_utils_common.httpAuthorizationToString)(options.sourceAuthorization), tier: (0, import_models.toAccessTier)(options.tier), blobTagsString: (0, import_utils_common.toBlobTagsString)(options.tags), immutabilityPolicyExpiry: options.immutabilityPolicy?.expiriesOn, immutabilityPolicyMode: options.immutabilityPolicy?.policyMode, legalHold: options.legalHold, encryptionScope: options.encryptionScope, copySourceTags: options.copySourceTags, fileRequestIntent: options.sourceShareTokenIntent, tracingOptions: updatedOptions.tracingOptions }) ); }); } /** * Sets the tier on a blob. The operation is allowed on a page blob in a premium * storage account and on a block blob in a blob storage account (locally redundant * storage only). A premium page blob's tier determines the allowed size, IOPS, * and bandwidth of the blob. A block blob's tier determines Hot/Cool/Archive * storage type. This operation does not update the blob's ETag. * @see https://learn.microsoft.com/rest/api/storageservices/set-blob-tier * * @param tier - The tier to be set on the blob. Valid values are Hot, Cool, or Archive. * @param options - Optional options to the Blob Set Tier operation. */ async setAccessTier(tier, options = {}) { return import_tracing.tracingClient.withSpan("BlobClient-setAccessTier", options, async (updatedOptions) => { return (0, import_utils_common.assertResponse)( await this.blobContext.setTier((0, import_models.toAccessTier)(tier), { abortSignal: options.abortSignal, leaseAccessConditions: options.conditions, modifiedAccessConditions: { ...options.conditions, ifTags: options.conditions?.tagConditions }, rehydratePriority: options.rehydratePriority, tracingOptions: updatedOptions.tracingOptions }) ); }); } async downloadToBuffer(param1, param2, param3, param4 = {}) { let buffer; let offset = 0; let count = 0; let options = param4; if (param1 instanceof Buffer) { buffer = param1; offset = param2 || 0; count = typeof param3 === "number" ? param3 : 0; } else { offset = typeof param1 === "number" ? param1 : 0; count = typeof param2 === "number" ? param2 : 0; options = param3 || {}; } let blockSize = options.blockSize ?? 0; if (blockSize < 0) { throw new RangeError("blockSize option must be >= 0"); } if (blockSize === 0) { blockSize = import_constants.DEFAULT_BLOB_DOWNLOAD_BLOCK_BYTES; } if (offset < 0) { throw new RangeError("offset option must be >= 0"); } if (count && count <= 0) { throw new RangeError("count option must be greater than 0"); } if (!options.conditions) { options.conditions = {}; } return import_tracing.tracingClient.withSpan( "BlobClient-downloadToBuffer", options, async (updatedOptions) => { if (!count) { const response = await this.getProperties({ ...options, tracingOptions: updatedOptions.tracingOptions }); count = response.contentLength - offset; if (count < 0) { throw new RangeError( `offset ${offset} shouldn't be larger than blob size ${response.contentLength}` ); } } if (!buffer) { try { buffer = Buffer.alloc(count); } catch (error) { throw new Error( `Unable to allocate the buffer of size: ${count}(in bytes). Please try passing your own buffer to the "downloadToBuffer" method or try using other methods like "download" or "downloadToFile". ${error.message}` ); } } if (buffer.length < count) { throw new RangeError( `The buffer's size should be equal to or larger than the request count of bytes: ${count}` ); } let transferProgress = 0; const batch = new import_Batch.Batch(options.concurrency); for (let off = offset; off < offset + count; off = off + blockSize) { batch.addOperation(async () => { let chunkEnd = offset + count; if (off + blockSize < chunkEnd) { chunkEnd = off + blockSize; } const response = await this.download(off, chunkEnd - off, { abortSignal: options.abortSignal, conditions: options.conditions, maxRetryRequests: options.maxRetryRequestsPerBlock, customerProvidedKey: options.customerProvidedKey, contentChecksumAlgorithm: options.contentChecksumAlgorithm, tracingOptions: updatedOptions.tracingOptions }); const stream = response.readableStreamBody; await (0, import_utils.streamToBuffer)(stream, buffer, off - offset, chunkEnd - offset); transferProgress += chunkEnd - off; if (options.onProgress) { options.onProgress({ loadedBytes: transferProgress }); } }); } await batch.do(); return buffer; } ); } /** * ONLY AVAILABLE IN NODE.JS RUNTIME. * * Downloads an Azure Blob to a local file. * Fails if the the given file path already exits. * Offset and count are optional, pass 0 and undefined respectively to download the entire blob. * * @param filePath - * @param offset - From which position of the block blob to download. * @param count - How much data to be downloaded. Will download to the end when passing undefined. * @param options - Options to Blob download options. * @returns The response data for blob download operation, * but with readableStreamBody set to undefined since its * content is already read and written into a local file * at the specified path. */ async downloadToFile(filePath, offset = 0, count, options = {}) { return import_tracing.tracingClient.withSpan("BlobClient-downloadToFile", options, async (updatedOptions) => { const response = await this.download(offset, count, { ...options, tracingOptions: updatedOptions.tracingOptions }); if (response.readableStreamBody) { await (0, import_utils.readStreamToLocalFile)(response.readableStreamBody, filePath); } response.blobDownloadStream = void 0; return response; }); } getBlobAndContainerNamesFromUrl() { let containerName; let blobName; try { const parsedUrl = new URL(this.url); if (parsedUrl.host.split(".")[1] === "blob") { const pathComponents = parsedUrl.pathname.match("/([^/]*)(/(.*))?"); containerName = pathComponents[1]; blobName = pathComponents[3]; } else if ((0, import_utils_common.isIpEndpointStyle)(parsedUrl)) { const pathComponents = parsedUrl.pathname.match("/([^/]*)/([^/]*)(/(.*))?"); containerName = pathComponents[2]; blobName = pathComponents[4]; } else { const pathComponents = parsedUrl.pathname.match("/([^/]*)(/(.*))?"); containerName = pathComponents[1]; blobName = pathComponents[3]; } containerName = decodeURIComponent(containerName); blobName = decodeURIComponent(blobName); blobName = blobName.replace(/\\/g, "/"); if (!containerName) { throw new Error("Provided containerName is invalid."); } return { blobName, containerName }; } catch (error) { throw new Error("Unable to extract blobName and containerName with provided information."); } } /** * Asynchronously copies a blob to a destination within the storage account. * In version 2012-02-12 and later, the source for a Copy Blob operation can be * a committed blob in any Azure storage account. * Beginning with version 2015-02-21, the source for a Copy Blob operation can be * an Azure file in any Azure storage account. * Only storage accounts created on or after June 7th, 2012 allow the Copy Blob * operation to copy from another storage account. * @see https://learn.microsoft.com/rest/api/storageservices/copy-blob * * @param copySource - url to the source Azure Blob/File. * @param options - Optional options to the Blob Start Copy From URL operation. */ async startCopyFromURL(copySource, options = {}) { return import_tracing.tracingClient.withSpan( "BlobClient-startCopyFromURL", options, async (updatedOptions) => { options.conditions = options.conditions || {}; options.sourceConditions = options.sourceConditions || {}; return (0, import_utils_common.assertResponse)( await this.blobContext.startCopyFromURL(copySource, { abortSignal: options.abortSignal, leaseAccessConditions: options.conditions, metadata: options.metadata, modifiedAccessConditions: { ...options.conditions, ifTags: options.conditions?.tagConditions }, sourceModifiedAccessConditions: { sourceIfMatch: options.sourceConditions.ifMatch, sourceIfModifiedSince: options.sourceConditions.ifModifiedSince, sourceIfNoneMatch: options.sourceConditions.ifNoneMatch, sourceIfUnmodifiedSince: options.sourceConditions.ifUnmodifiedSince, sourceIfTags: options.sourceConditions.tagConditions }, immutabilityPolicyExpiry: options.immutabilityPolicy?.expiriesOn, immutabilityPolicyMode: options.immutabilityPolicy?.policyMode, legalHold: options.legalHold, rehydratePriority: options.rehydratePriority, tier: (0, import_models.toAccessTier)(options.tier), blobTagsString: (0, import_utils_common.toBlobTagsString)(options.tags), sealBlob: options.sealBlob, tracingOptions: updatedOptions.tracingOptions }) ); } ); } /** * Only available for BlobClient constructed with a shared key credential. * * Generates a Blob Service Shared Access Signature (SAS) URI based on the client properties * and parameters passed in. The SAS is signed by the shared key credential of the client. * * @see https://learn.microsoft.com/rest/api/storageservices/constructing-a-service-sas * * @param options - Optional parameters. * @returns The SAS URI consisting of the URI to the resource represented by this client, followed by the generated SAS token. */ generateSasUrl(options) { return new Promise((resolve) => { if (!(this.credential instanceof import_storage_common.StorageSharedKeyCredential)) { throw new RangeError( "Can only generate the SAS when the client is initialized with a shared key credential" ); } const sas = (0, import_BlobSASSignatureValues.generateBlobSASQueryParameters)( { containerName: this._containerName, blobName: this._name, snapshotTime: this._snapshot, versionId: this._versionId, ...options }, this.credential ).toString(); resolve((0, import_utils_common.appendToURLQuery)(this.url, sas)); }); } /** * Only available for BlobClient constructed with a shared key credential. * * Generates string to sign for a Blob Service Shared Access Signature (SAS) URI based on * the client properties and parameters passed in. The SAS is signed by the shared key credential of the client. * * @see https://learn.microsoft.com/rest/api/storageservices/constructing-a-service-sas * * @param options - Optional parameters. * @returns The SAS URI consisting of the URI to the resource represented by this client, followed by the generated SAS token. */ /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ generateSasStringToSign(options) { if (!(this.credential instanceof import_storage_common.StorageSharedKeyCredential)) { throw new RangeError( "Can only generate the SAS when the client is initialized with a shared key credential" ); } return (0, import_BlobSASSignatureValues.generateBlobSASQueryParametersInternal)( { containerName: this._containerName, blobName: this._name, snapshotTime: this._snapshot, versionId: this._versionId, ...options }, this.credential ).stringToSign; } /** * * Generates a Blob Service Shared Access Signature (SAS) URI based on * the client properties and parameters passed in. The SAS is signed by the input user delegation key. * * @see https://learn.microsoft.com/rest/api/storageservices/constructing-a-service-sas * * @param options - Optional parameters. * @param userDelegationKey - Return value of `blobServiceClient.getUserDelegationKey()` * @returns The SAS URI consisting of the URI to the resource represented by this client, followed by the generated SAS token. */ generateUserDelegationSasUrl(options, userDelegationKey) { return new Promise((resolve) => { const sas = (0, import_BlobSASSignatureValues.generateBlobSASQueryParameters)( { containerName: this._containerName, blobName: this._name, snapshotTime: this._snapshot, versionId: this._versionId, ...options }, userDelegationKey, this.accountName ).toString(); resolve((0, import_utils_common.appendToURLQuery)(this.url, sas)); }); } /** * Only available for BlobClient constructed with a shared key credential. * * Generates string to sign for a Blob Service Shared Access Signature (SAS) URI based on * the client properties and parameters passed in. The SAS is signed by the input user delegation key. * * @see https://learn.microsoft.com/rest/api/storageservices/constructing-a-service-sas * * @param options - Optional parameters. * @param userDelegationKey - Return value of `blobServiceClient.getUserDelega