@azure/storage-blob
Version:
Microsoft Azure Storage SDK for JavaScript - Blob
1,144 lines • 138 kB
JavaScript
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