UNPKG

azure-storage-legacy

Version:

Microsoft Azure Storage Client Library for node for back compat with older versions of node sdk

984 lines (850 loc) 190 kB
// // Copyright (c) Microsoft and contributors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // // See the License for the specific language governing permissions and // limitations under the License. // // Module dependencies. var fs = require('fs'); var qs = require('querystring'); var url = require('url'); var util = require('util'); var mime = require('mime'); var _ = require('underscore'); var crypto = require('crypto'); var FileReadStream = require('./internal/filereadstream'); var BlobBlockRangeStream = require('./internal/blobblockrangestream'); var BlobPageRangeStream = require('./internal/blobpagerangestream'); var BatchOperation = require('./internal/batchoperation'); var SpeedSummary = require('./internal/speedsummary'); var ChunkAllocator = require('./internal/chunkAllocator'); var ChunkStream = require('./internal/chunkStream'); var ChunkStreamWithStream = require('./internal/chunkStreamWithStream'); var azureCommon = require('azure-common'); var azureutil = azureCommon.util; var validate = azureCommon.validate; var requestPipeline = azureCommon.requestPipeline; var ErrorHandlingFilter = azureCommon.ErrorHandlingFilter; var UserAgentFilter = azureCommon.UserAgentFilter; var SigningFilter = azureCommon.SigningFilter; var StorageServiceClient = azureCommon.StorageServiceClient; var WebResource = azureCommon.WebResource; var Constants = azureCommon.Constants; var HeaderConstants = Constants.HeaderConstants; var QueryStringConstants = Constants.QueryStringConstants; var BlobConstants = Constants.BlobConstants; var SharedKey = require('./internal/sharedkey'); var SharedAccessSignature = require('./internal/sharedaccesssignature'); // Models requires var servicePropertiesResult = require('./models/servicepropertiesresult'); var ContainerAclResult = require('./models/containeraclresult'); var BlockListResult = require('./models/blocklistresult'); var BlobResult = require('./models/blobresult'); var ContainerResult = require('./models/containerresult'); var LeaseResult = require('./models/leaseresult'); var ListBlobsResultContinuation = require('./models/listblobsresultcontinuation'); var ListContainersResultContinuation = require('./models/listcontainersresultcontinuation'); /** * Creates a new BlobService object. * If no storageaccount or storageaccesskey are provided, * the AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY environment variables will be used. * @class * The BlobService class is used to perform operations on the Microsoft Azure Blob Service. * The Blob Service provides storage for binary large objects, and provides * functions for working with data stored in blobs as either streams or pages of data. * * For more information on the Blob Service, as well as task focused information on using it in a Node.js application, see * [How to Use the Blob Service from Node.js](https://www.windowsazure.com/en-us/develop/nodejs/how-to-guides/blob-storage/). * @constructor * @extends {ServiceClient} * * @param {string} [storageAccountOrConnectionString] The storage account or the connection string. * @param {string} [storageAccessKey] The storage access key. * @param {string} [host] The host address. * @param {object} [authenticationProvider] The authentication provider. */ function BlobService(storageAccountOrConnectionString, storageAccessKey, host, authenticationProvider) { var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host); BlobService['super_'].call(this, storageServiceSettings._name, storageServiceSettings._key, storageServiceSettings._blobEndpointUri, storageServiceSettings._usePathStyleUri, authenticationProvider); this.apiVersion = '2012-02-12'; if (!this.authenticationProvider) { this.authenticationProvider = new SharedKey(this.storageAccount, this.storageAccessKey, this.usePathStyleUri); } if (!this.sharedAccessSignatureCredentials) { this.sharedAccessSignatureCredentials = new SharedAccessSignature(this.storageAccount, this.storageAccessKey); } this.singleBlobPutThresholdInBytes = BlobConstants.DEFAULT_SINGLE_BLOB_PUT_THRESHOLD_IN_BYTES; this.writeBlockSizeInBytes = BlobConstants.DEFAULT_WRITE_BLOCK_SIZE_IN_BYTES; this.pipeline = requestPipeline.create( SigningFilter.create(this.authenticationProvider), UserAgentFilter.create(), ErrorHandlingFilter.create()); } util.inherits(BlobService, StorageServiceClient); // Non-class methods /** * Create resource name * @ignore * * @param {string} containerName Container name * @param {string} blobName Blob name * @param {bool} skipEncoding Boolean value indicating if encoding should be skipped. * @return {string} The encoded resource name. */ function createResourceName(containerName, blobName, skipEncoding) { // Resource name if (!skipEncoding) { if (blobName) { blobName = encodeURIComponent(blobName); blobName = blobName.replace(/%2F/g, '/'); blobName = blobName.replace(/%5C/g, '/'); blobName = blobName.replace(/\+/g, '%20'); } } var resourceName = containerName + '/' + blobName; if (!containerName || containerName === '$root') { resourceName = blobName; } if (!blobName) { resourceName = containerName; } return resourceName; } /** * Gets the properties of a storage account’s Blob service, including Microsoft Azure Storage Analytics. * * @this {BlobService} * @param {object} [options] The request options. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {Function(error, serviceProperties, response)} callback `error` will contain information * if an error occurs; otherwise, `serviceProperties` * will contain the properties and `response` * will contain information related to this operation. */ BlobService.prototype.getServiceProperties = function (optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('getServiceProperties', function (v) { v.callback(callback); }); var webResource = WebResource.get() .withQueryOption(QueryStringConstants.COMP, 'properties') .withQueryOption(QueryStringConstants.RESTYPE, 'service'); var processResponseCallback = function (responseObject, next) { responseObject.servicePropertiesResult = null; if (!responseObject.error) { responseObject.servicePropertiesResult = servicePropertiesResult.parse(responseObject.response.body.StorageServiceProperties); } // function to be called after all filters var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.servicePropertiesResult, returnObject.response); }; // call the first filter next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Sets the properties of a storage account’s Blob service, including Microsoft Azure Storage Analytics. * You can also use this operation to set the default request version for all incoming requests that do not have a version specified. * * @this {BlobService} * @param {object} serviceProperties The service properties. * @param {object} [options] The request options. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, * to use for the request. * @param {Function(error, response)} callback `error` will contain information * if an error occurs; otherwise, `response` * will contain information related to this operation. */ BlobService.prototype.setServiceProperties = function (serviceProperties, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('setServiceProperties', function (v) { v.object(serviceProperties, 'serviceProperties'); v.callback(callback); }); var servicePropertiesXml = servicePropertiesResult.serialize(serviceProperties); var webResource = WebResource.put() .withQueryOption(QueryStringConstants.COMP, 'properties') .withQueryOption(QueryStringConstants.RESTYPE, 'service') .withHeader(HeaderConstants.CONTENT_TYPE, 'application/xml;charset="utf-8"') .withHeader(HeaderConstants.CONTENT_LENGTH, Buffer.byteLength(servicePropertiesXml)) .withBody(servicePropertiesXml); var processResponseCallback = function (responseObject, next) { var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, webResource.body, options, processResponseCallback); }; /** * Returns a list of the containers under the specified account. * * @this {BlobService} * @param {object} [options] The list container options. * @param {string} [options.prefix] Filters the results to return only containers whose name begins with the specified prefix. * @param {int} [options.maxresults] Specifies the maximum number of containers to return per call to Azure storage. * @param {string} [options.marker] String value that identifies the portion of the list to be returned with the next list operation. * @param {string} [options.include] Include this parameter to specify that the container's metadata be returned as part of the response body. (allowed values: '', 'metadata') * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {Function(error, containers, nextMarker, response)} callback `error` will contain information * if an error occurs; otherwise `containers` will contain a list of * {@link BlobService~containerResult} objects, * and `response` will contain information related to this operation. * If not all container information could be retrieved, * `nextMarker` will contain a value that can be used * to retrieve the next section of the containers list. */ BlobService.prototype.listContainers = function (optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('listContainers', function (v) { v.callback(callback); }); var webResource = WebResource.get() .withProperty(BlobConstants.ResourceTypeProperty, BlobConstants.ResourceTypes.CONTAINER) .withProperty(BlobConstants.SharedAccessPermissionProperty, BlobConstants.SharedAccessPermissions.LIST) .withQueryOption(QueryStringConstants.COMP, 'list') .withQueryOptions(options, QueryStringConstants.PREFIX, QueryStringConstants.MARKER, QueryStringConstants.MAX_RESULTS, QueryStringConstants.INCLUDE); var self = this; var processResponseCallback = function (responseObject, next) { responseObject.listContainersResult = null; responseObject.listContainersResultContinuation = null; if (!responseObject.error) { responseObject.listContainersResult = []; if (responseObject.response.body.EnumerationResults.Containers && responseObject.response.body.EnumerationResults.Containers.Container) { var containers = responseObject.response.body.EnumerationResults.Containers.Container; if (!_.isArray(containers)) { containers = [ containers ]; } containers.forEach(function (currentContainer) { var containerResult = ContainerResult.parse(currentContainer); responseObject.listContainersResult.push(containerResult); }); responseObject.listContainersResultContinuation = new ListContainersResultContinuation(self, options, responseObject.response.body.EnumerationResults.NextMarker); } } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.listContainersResult, returnObject.listContainersResultContinuation, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Creates a new container under the specified account. * If a container with the same name already exists, the operation fails. * * @this {BlobService} * @param {string} container The container name. * @param {object} [options] The optional container and request options. * @param {object} [options.metadata] The metadata key/value pairs. * @param {string} [options.publicAccessLevel] Specifies whether data in the container may be accessed publicly and the level of access. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {function(error, container, response)} callback `error` will contain information * if an error occurs; otherwise `container` will contain * the {@link BlobService~containerResult} for the container. * `response` will contain information related to this operation. */ BlobService.prototype.createContainer = function (container, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('createContainer', function (v) { v.string(container, 'container'); v.test(function () { return container !== '$logs'; }, 'Container name format is incorrect'); v.containerNameIsValid(container); v.callback(callback); }); var webResource = WebResource.put(container) .withProperty(BlobConstants.ResourceTypeProperty, BlobConstants.ResourceTypes.CONTAINER) .withProperty(BlobConstants.SharedAccessPermissionProperty, BlobConstants.SharedAccessPermissions.WRITE) .withQueryOption(QueryStringConstants.RESTYPE, 'container'); if (options) { webResource.addOptionalMetadataHeaders(options.metadata); webResource.withHeader(HeaderConstants.BLOB_PUBLIC_ACCESS_HEADER, options.publicAccessLevel); } var processResponseCallback = function (responseObject, next) { responseObject.containerResult = null; if (!responseObject.error) { responseObject.containerResult = new ContainerResult(container); responseObject.containerResult.getPropertiesFromHeaders(responseObject.response.headers); if (options && options.metadata) { responseObject.containerResult.metadata = options.metadata; } } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.containerResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Creates a new container under the specified account if the container does not exists. * * @this {BlobService} * @param {string} container The container name. * @param {object} [options] The optional container and request options. * @param {object} [options.metadata] The metadata key/value pairs. * @param {string} [options.publicAccessLevel] Specifies whether data in the container may be accessed publicly and the level of access. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {Function(error, containerCreated, response)} callback `error` will contain information * if an error occurs; otherwise `containerCreated` will contain * be true if the container was created, or false if the container * already exists. * `response` will contain information related to this operation. * * @example * var azure = require('azure'); * var blobService = azure.createBlobService(); * blobService.createContainerIfNotExists('taskcontainer', {publicAccessLevel : 'blob'}, function(error) { * if(!error) { * // Container created or exists, and is public * } * }); */ BlobService.prototype.createContainerIfNotExists = function (container, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('createContainerIfNotExists', function (v) { v.callback(callback); }); this.createContainer(container, options, function (error, responseContainer, response) { if (error && error.code === Constants.BlobErrorCodeStrings.CONTAINER_ALREADY_EXISTS) { // If it was created before, there was no actual error. error = null; } callback(error, !azureutil.objectIsNull(responseContainer), response); }); }; /** * Retrieves a container and its properties from a specified account. * * @this {BlobService} * @param {string} container The container name. * @param {object} [options] The request options. * @param {string} [options.leaseId] The target blob lease identifier. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {Function(error, container, response)} callback `error` will contain information * if an error occurs; otherwise `container` will contain * the {@link BlobService~containerResult} information for the container. * `response` will contain information related to this operation. */ BlobService.prototype.getContainerProperties = function (container, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('getContainerProperties', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var webResource = WebResource.head(container) .withProperty(BlobConstants.ResourceTypeProperty, BlobConstants.ResourceTypes.CONTAINER) .withProperty(BlobConstants.SharedAccessPermissionProperty, BlobConstants.SharedAccessPermissions.READ) .withQueryOption(QueryStringConstants.RESTYPE, 'container'); if (options) { if (options.leaseId) { webResource.withHeader(HeaderConstants.LEASE_ID_HEADER, options.leaseId); } } var self = this; var processResponseCallback = function (responseObject, next) { responseObject.containerResult = null; if (!responseObject.error) { responseObject.containerResult = new ContainerResult(container); responseObject.containerResult.metadata = self.parseMetadataHeaders(responseObject.response.headers); responseObject.containerResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.containerResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Returns all user-defined metadata for the container. * * @this {BlobService} * @param {string} container The container name. * @param {object} [options] The request options. * @param {string} [options.leaseId] The target blob lease identifier. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {Function(error, container, response)} callback `error` will contain information * if an error occurs; otherwise `container` will contain * the {@link BlobService~containerResult} information for the container. * `response` will contain information related to this operation. */ BlobService.prototype.getContainerMetadata = function (container, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('getContainerMetadata', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var webResource = WebResource.head(container) .withProperty(BlobConstants.ResourceTypeProperty, BlobConstants.ResourceTypes.CONTAINER) .withProperty(BlobConstants.SharedAccessPermissionProperty, BlobConstants.SharedAccessPermissions.READ) .withQueryOption(QueryStringConstants.RESTYPE, 'container') .withQueryOption(QueryStringConstants.COMP, 'metadata'); if (options) { if (options.leaseId) { webResource.withHeader(HeaderConstants.LEASE_ID_HEADER, options.leaseId); } } var self = this; var processResponseCallback = function (responseObject, next) { responseObject.containerResult = null; if (!responseObject.error) { responseObject.containerResult = new ContainerResult(container); responseObject.containerResult.metadata = self.parseMetadataHeaders(responseObject.response.headers); responseObject.containerResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.containerResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Sets the container's metadata. * * Calling the Set Container Metadata operation overwrites all existing metadata that is associated with the container. * It's not possible to modify an individual name/value pair. * * @this {BlobService} * @param {string} container The container name. * @param {object} metadata The metadata key/value pairs. * @param {object} [options] The container and request options. * @param {string} [options.leaseId] The target blob lease identifier. * @param {object} [options.accessConditions] See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {Function(error, response)} callback `error` will contain information * if an error occurs; otherwise * `response` will contain information related to this operation. */ BlobService.prototype.setContainerMetadata = function (container, metadata, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('setContainerMetadata', function (v) { v.string(container, 'container'); v.object(metadata, 'metadata'); v.containerNameIsValid(container); v.callback(callback); }); var webResource = WebResource.put(container) .withProperty(BlobConstants.ResourceTypeProperty, BlobConstants.ResourceTypes.CONTAINER) .withProperty(BlobConstants.SharedAccessPermissionProperty, BlobConstants.SharedAccessPermissions.WRITE) .withQueryOption(QueryStringConstants.RESTYPE, 'container') .withQueryOption(QueryStringConstants.COMP, 'metadata'); webResource.addOptionalMetadataHeaders(metadata); if (options) { if (options.leaseId) { webResource.withHeader(HeaderConstants.LEASE_ID_HEADER, options.leaseId); } } var processResponseCallback = function (responseObject, next) { var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Gets the container's ACL. * * @this {BlobService} * @param {string} container The container name. * @param {object} [options] The container and request options. * @param {string} [options.leaseId] The target blob lease identifier. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {Function(error, container, response)} callback `error` will contain information * if an error occurs; otherwise `container` will contain * the {@link BlobService~containerResult} information for the container. * `response` will contain information related to this operation. */ BlobService.prototype.getContainerAcl = function (container, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('getContainerAcl', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var webResource = WebResource.get(container) .withProperty(BlobConstants.ResourceTypeProperty, BlobConstants.ResourceTypes.CONTAINER) .withProperty(BlobConstants.SharedAccessPermissionProperty, BlobConstants.SharedAccessPermissions.READ) .withQueryOption(QueryStringConstants.RESTYPE, 'container') .withQueryOption(QueryStringConstants.COMP, 'acl'); if (options) { if (options.leaseId) { webResource.withHeader(HeaderConstants.LEASE_ID_HEADER, options.leaseId); } } var processResponseCallback = function (responseObject, next) { responseObject.containerResult = null; if (!responseObject.error) { responseObject.containerResult = new ContainerResult(container); responseObject.containerResult.getPropertiesFromHeaders(responseObject.response.headers); responseObject.containerResult.signedIdentifiers = ContainerAclResult.parse(responseObject.response.body); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.containerResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Updates the container's ACL. * * @this {BlobService} * @param {string} container The container name. * @param {string} publicAccessLevel Specifies whether data in the container may be accessed publicly and the level of access. * @param {object} [options] The container and request options. * @param {string} [options.leaseId] The target blob lease identifier. * @param {object} [options.signedIdentifiers] The signed identifiers. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {Function(error, container, response)} callback `error` will contain information * if an error occurs; otherwise `container` will contain * the {@link BlobService~containerResult} information for the container. * `response` will contain information related to this operation. */ BlobService.prototype.setContainerAcl = function (container, publicAccessLevel, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('setContainerAcl', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var policies = null; if (options && options.signedIdentifiers) { if (!_.isArray(options.signedIdentifiers)) { throw new Error('Signed identifiers need to be an array'); } policies = ContainerAclResult.serialize(options.signedIdentifiers); } var webResource = WebResource.put(container) .withProperty(BlobConstants.ResourceTypeProperty, BlobConstants.ResourceTypes.CONTAINER) .withProperty(BlobConstants.SharedAccessPermissionProperty, BlobConstants.SharedAccessPermissions.WRITE) .withQueryOption(QueryStringConstants.RESTYPE, 'container') .withQueryOption(QueryStringConstants.COMP, 'acl') .withHeader(HeaderConstants.CONTENT_LENGTH, !azureutil.objectIsNull(policies) ? Buffer.byteLength(policies) : 0) .withBody(policies); if (publicAccessLevel) { webResource.withHeader(HeaderConstants.BLOB_PUBLIC_ACCESS_HEADER, publicAccessLevel); } if (options) { if (options.leaseId) { webResource.withHeader(HeaderConstants.LEASE_ID_HEADER, options.leaseId); } } var processResponseCallback = function (responseObject, next) { responseObject.containerResult = null; if (!responseObject.error) { responseObject.containerResult = new ContainerResult(container, publicAccessLevel); responseObject.containerResult.getPropertiesFromHeaders(responseObject.response.headers); if (options && options.signedIdentifiers) { responseObject.containerResult.signedIdentifiers = options.signedIdentifiers; } } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.containerResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, webResource.body, options, processResponseCallback); }; /** * Marks the specified container for deletion. * The container and any blobs contained within it are later deleted during garbage collection. * * @this {BlobService} * @param {string} container The container name. * @param {object} [options] The container and request options. * @param {string} [options.leaseId] The target blob lease identifier. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {Function(error, response)} callback `error` will contain information * if an error occurs; otherwise * `response` will contain information related to this operation. */ BlobService.prototype.deleteContainer = function (container, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('deleteContainer', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var webResource = WebResource.del(container) .withProperty(BlobConstants.ResourceTypeProperty, BlobConstants.ResourceTypes.CONTAINER) .withProperty(BlobConstants.SharedAccessPermissionProperty, BlobConstants.SharedAccessPermissions.WRITE) .withQueryOption(QueryStringConstants.RESTYPE, 'container'); if (options) { if (options.leaseId) { webResource.withHeader(HeaderConstants.LEASE_ID_HEADER, options.leaseId); } } var processResponseCallback = function (responseObject, next) { var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Lists all of the blobs in the given container. * * @this {BlobService} * @param {string} container The container name. * @param {object} [options] The listing and request options. * @param {string} [options.prefix] The blob name prefix. * @param {string} [options.delimiter] Delimiter, i.e. '/', for specifying folder hierarchy. * @param {int} [options.maxresults] Specifies the maximum number of blobs to return per call to Azure ServiceClient. This does NOT affect list size returned by this function. (maximum: 5000) * @param {string} [options.marker] String value that identifies the portion of the list to be returned with the next list operation. * @param {string} [options.include] Specifies that the response should include one or more of the following subsets: '', 'metadata', 'snapshots', 'uncommittedblobs'). Multiple values can be added separated with a comma (,) * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {Function(error, blobs, response)} callback `error` will contain information * if an error occurs; otherwise `blobs` will contain * the blobs within the container. * `response` will contain information related to this operation. */ BlobService.prototype.listBlobs = function (container, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('listBlobs', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var webResource = WebResource.get(container) .withProperty(BlobConstants.ResourceTypeProperty, BlobConstants.ResourceTypes.BLOB) .withProperty(BlobConstants.SharedAccessPermissionProperty, BlobConstants.SharedAccessPermissions.LIST) .withQueryOption(QueryStringConstants.RESTYPE, 'container') .withQueryOption(QueryStringConstants.COMP, 'list') .withQueryOptions(options, QueryStringConstants.PREFIX, QueryStringConstants.MARKER, QueryStringConstants.MAX_RESULTS, QueryStringConstants.DELIMITER, QueryStringConstants.INCLUDE); var self = this; var processResponseCallback = function (responseObject, next) { responseObject.listBlobsResult = null; responseObject.listBlobsResultContinuation = null; if (!responseObject.error) { responseObject.listBlobsResult = []; var blobs = []; if (responseObject.response.body.EnumerationResults.Blobs.Blob) { blobs = responseObject.response.body.EnumerationResults.Blobs.Blob; if (!_.isArray(blobs)) { blobs = [ blobs ]; } } blobs.forEach(function (currentBlob) { var blobResult = BlobResult.parse(currentBlob); responseObject.listBlobsResult.push(blobResult); }); responseObject.listBlobsResultContinuation = new ListBlobsResultContinuation(self, container, options, responseObject.response.body.EnumerationResults.NextMarker); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.listBlobsResult, returnObject.listBlobsResultContinuation, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Writes a range of pages to a page blob. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {int} length The length of the page blob in bytes. * @param {object} [options] The page blob and request options. * @param {object} [options.metadata] The metadata key/value pairs. * @param {string} [options.leaseId] The target blob lease identifier. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {Function(error, response)} callback `error` will contain information * if an error occurs; otherwise * `response` will contain information related to this operation. */ BlobService.prototype.createPageBlob = function (container, blob, length, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('createPageBlob', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.blobNameIsValid(container, blob); v.callback(callback); }); var resourceName = createResourceName(container, blob); var webResource = WebResource.put(resourceName) .withProperty(BlobConstants.ResourceTypeProperty, BlobConstants.ResourceTypes.BLOB) .withProperty(BlobConstants.SharedAccessPermissionProperty, BlobConstants.SharedAccessPermissions.WRITE) .withHeader(HeaderConstants.BLOB_TYPE_HEADER, BlobConstants.BlobTypes.PAGE) .withHeader(HeaderConstants.CONTENT_LENGTH_HEADER, length) .withHeader(HeaderConstants.CONTENT_LENGTH, 0); if (options) { webResource.withHeader(HeaderConstants.LEASE_ID_HEADER, options.leaseId); webResource.addOptionalMetadataHeaders(options.metadata); } var processResponseCallback = function (responseObject, next) { var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Creates a new block blob or page blob, or updates the content of an existing block blob. * Updating an existing block blob overwrites any existing metadata on the blob. Partial updates are not supported with Put Blob; the content of the existing blob is overwritten with the content of the new blob. To perform a partial update of the content of a block blob, use the Put Block List operation. * Calling Put Blob to create a page blob only initializes the blob. To add content to a page blob, call the Put Page operation. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {string} localFilename The local path to the file to be uploaded. * @param {object} [options] The creating and request options. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.setBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. This field is not supported for page blobs. The default value is false. * @param {string} [options.contentType] The MIME content type of the blob. The default type is application/octet-stream. * @param {string} [options.contentEncoding] The content encodings that have been applied to the blob. * @param {string} [options.contentLanguage] The natural languages used by this resource. * @param {string} [options.contentMD5] The MD5 hash of the blob content. * @param {string} [options.cacheControl] The Blob service stores this value but does not use or modify it. * @param {string} [options.contentTypeHeader] The blob’s content type. (x-ms-blob-content-type) * @param {string} [options.contentEncodingHeader] The blob’s content encoding. (x-ms-blob-content-encoding) * @param {string} [options.contentLanguageHeader] The blob's content language. (x-ms-blob-content-language) * @param {string} [options.contentMD5Header] The blob’s MD5 hash. (x-ms-blob-content-md5) * @param {string} [options.cacheControlHeader] The blob's cache control. (x-ms-blob-cache-control) * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {Function(error, blockBlob, response)} callback `error` will contain information * if an error occurs; otherwise `blockBlob` will contain * information about the blob. * `response` will contain information related to this operation. * @return {undefined} */ BlobService.prototype.putBlockBlobFromFile = function (container, blob, localFilename, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('putBlockBlobFromFile', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.blobNameIsValid(container, blob); v.callback(callback); }); var self = this; if (!options.speedSummary) { options.speedSummary = new SpeedSummary(blob); } var operation = function (length, md5) { if (md5 && !blob.contentMD5) { blob.contentMD5 = md5; } if (!options) { options = {}; } if (options.contentType === undefined) { options.contentType = mime.getType(localFilename); } if (options.contentTypeHeader === undefined) { options.contentTypeHeader = mime.getType(localFilename); } if (length >= BlobConstants.MAX_SINGLE_UPLOAD_BLOB_SIZE_IN_BYTES) { throw new Error('Invalid file size for a single block. Please use the createBlockBlobFromFile to upload large file.'); } else { var readStream = fs.createReadStream(localFilename); self.putBlockBlobFromStream(container, blob, readStream, length, options, callback); } }; var calculateMD5 = (options && options.setBlobContentMD5 && !options[HeaderConstants.CONTENT_MD5]); if (calculateMD5) { var stream = fs.createReadStream(localFilename); azureutil.analyzeStream(stream, calculateMD5, operation); } else { fs.stat(localFilename, function (statErr, stat) { if (statErr) { callback(statErr); } else { operation(stat.size); } }); } return options.speedSummary; }; /** * Uploads a block blob from a stream. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param (Stream) stream Stream to the data to store. * @param {int} streamLength The length of the stream to upload. * @param {object} [options] The creating and request options. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.setBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. This field is not supported for page blobs. The default value is false. * @param {string} [options.contentType] The MIME content type of the blob. The default type is application/octet-stream. * @param {string} [options.contentEncoding] The content encodings that have been applied to the blob. * @param {string} [options.contentLanguage] The natural languages used by this resource. * @param {string} [options.contentMD5] The MD5 hash of the blob content. * @param {string} [options.cacheControl] The Blob service stores this value but does not use or modify it. * @param {string} [options.contentTypeHeader] The blob’s content type. (x-ms-blob-content-type) * @param {string} [options.contentEncodingHeader] The blob’s content encoding. (x-ms-blob-content-encoding) * @param {string} [options.contentLanguageHeader] The blob's content language. (x-ms-blob-content-language) * @param {string} [options.contentMD5Header] The blob’s MD5 hash. (x-ms-blob-content-md5) * @param {string} [options.cacheControlHeader] The blob's cache control. (x-ms-blob-cache-control) * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {Function(error, blockBlob, response)} callback `error` will contain information * if an error occurs; otherwise `blockBlob` will contain * information about the blob. * `response` will contain information related to this operation. * @return {undefined} * * @example * var azure = require('azure'); * var blobService = azure.createBlobService(); * blobService.putBlockBlobFromStream('taskcontainer', 'task1', fs.createReadStream('task1-upload.txt'), 11, function(error) { * if(!error) { * // Blob uploaded * } * }); */ BlobService.prototype.putBlockBlobFromStream = function (container, blob, readStream, streamLength, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('putBlockBlobFromStream', fu