// // 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('browserify-mime'); var _ = require('underscore'); var crypto = require('crypto'); var extend = require('extend'); var azureCommon = require('./../../common/common'); var BlockRangeStream = require('./internal/blockrangestream'); var PageRangeStream = require('./internal/pagerangestream'); var RangeStream = require('./../../common/streams/rangestream'); var azureutil = azureCommon.util; var SR = azureCommon.SR; var validate = azureCommon.validate; var StorageServiceClient = azureCommon.StorageServiceClient; var WebResource = azureCommon.WebResource; // Constants var Constants = azureCommon.Constants; var BlobConstants = Constants.BlobConstants; var HeaderConstants = Constants.HeaderConstants; var QueryStringConstants = Constants.QueryStringConstants; var RequestLocationMode = Constants.RequestLocationMode; // Streams var BatchOperation = azureCommon.BatchOperation; var SpeedSummary = azureCommon.SpeedSummary; var ChunkAllocator = azureCommon.ChunkAllocator; var ChunkStream = azureCommon.ChunkStream; var ChunkStreamWithStream = azureCommon.ChunkStreamWithStream; var FileReadStream = azureCommon.FileReadStream; // Models requires var AclResult = azureCommon.AclResult; var ServiceStatsParser = azureCommon.ServiceStatsParser; var BlockListResult = require('./models/blocklistresult'); var BlobResult = require('./models/blobresult'); var ContainerResult = require('./models/containerresult'); var LeaseResult = require('./models/leaseresult'); var BlobUtilities = require('./blobutilities'); /** * Creates a new BlobService object. * If no connection string or storageaccount and storageaccesskey are provided, * the AZURE_STORAGE_CONNECTION_STRING or 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](http://azure.microsoft.com/en-us/documentation/articles/storage-nodejs-how-to-use-blob-storage/). * The following defaults can be set on the blob service. * singleBlobPutThresholdInBytes The default maximum size, in bytes, of a blob before it must be separated into blocks. * defaultTimeoutIntervalInMs The default timeout interval, in milliseconds, to use for request made via the Blob service. * defaultMaximumExecutionTimeInMs The default maximum execution time across all potential retries, for requests made via the Blob service. * defaultLocationMode The default location mode for requests made via the Blob service. * parallelOperationThreadCount The number of parallel operations that may be performed when uploading a blob that is greater than * the value specified by the singleBlobPutThresholdInBytes property in size. * useNagleAlgorithm Determines whether the Nagle algorithm is used for requests made via the Blob service; true to use the * Nagle algorithm; otherwise, false. The default value is false. * @constructor * @extends {StorageServiceClient} * * @param {string} [storageAccountOrConnectionString] The storage account or the connection string. * @param {string} [storageAccessKey] The storage access key. * @param {string|object} [host] The host address. To define primary only, pass a string. * Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host. * @param {string} [sasToken] The Shared Access Signature token. */ function BlobService(storageAccountOrConnectionString, storageAccessKey, host, sasToken) { var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host, sasToken); BlobService['super_'].call(this, storageServiceSettings._name, storageServiceSettings._key, storageServiceSettings._blobEndpoint, storageServiceSettings._usePathStyleUri, storageServiceSettings._sasToken); this.singleBlobPutThresholdInBytes = BlobConstants.DEFAULT_SINGLE_BLOB_PUT_THRESHOLD_IN_BYTES; this.parallelOperationThreadCount = Constants.DEFAULT_PARALLEL_OPERATION_THREAD_COUNT; } util.inherits(BlobService, StorageServiceClient); // Non-class methods /** * Create resource name * @ignore * * @param {string} containerName Container name * @param {string} blobName Blob name * @return {string} The encoded resource name. */ function createResourceName(containerName, blobName, forSAS) { // Resource name if (blobName && !forSAS) { blobName = encodeURIComponent(blobName); blobName = blobName.replace(/%2F/g, '/'); blobName = blobName.replace(/%5C/g, '/'); blobName = blobName.replace(/\+/g, '%20'); } // return URI encoded resource name if (blobName) { return containerName + '/' + blobName; } else { return containerName; } } // Blob service methods /** * Gets the service stats for a storage account’s Blob service. * * @this {BlobService} * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; otherwise, `result` will contain the stats and * `response` will contain information related to this operation. */ BlobService.prototype.getServiceStats = function (optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('getServiceStats', function (v) { v.callback(callback); }); var webResource = WebResource.get() .withQueryOption(QueryStringConstants.COMP, 'stats') .withQueryOption(QueryStringConstants.RESTYPE, 'service'); options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY; var processResponseCallback = function (responseObject, next) { responseObject.serviceStatsResult = null; if (!responseObject.error) { responseObject.serviceStatsResult = ServiceStatsParser.parse(responseObject.response.body.StorageServiceStats); } // function to be called after all filters var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.serviceStatsResult, returnObject.response); }; // call the first filter next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Gets the properties of a storage account’s Blob service, including Azure Storage Analytics. * * @this {BlobService} * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; otherwise, `result` will contain the properties * and `response` will contain information related to this operation. */ BlobService.prototype.getServiceProperties = function (optionsOrCallback, callback) { return this.getAccountServiceProperties(optionsOrCallback, callback); }; /** * Sets the properties of a storage account’s Blob service, including 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 {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} 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) { return this.setAccountServiceProperties(serviceProperties, optionsOrCallback, callback); }; /** * Lists a segment containing a collection of container items under the specified account. * * @this {BlobService} * @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.maxResults] Specifies the maximum number of containers to return per call to Azure storage. * @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 server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain `entries` and `continuationToken`. * `entries` gives a list of containers and the `continuationToken` is used for the next listing operation. * `response` will contain information related to this operation. */ BlobService.prototype.listContainersSegmented = function (currentToken, optionsOrCallback, callback) { this.listContainersSegmentedWithPrefix(null /* prefix */, currentToken, optionsOrCallback, callback); }; /** * Lists a segment containing a collection of container items whose names begin with the specified prefix under the specified account. * * @this {BlobService} * @param {string} prefix The prefix of the container name. * @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @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.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 server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain `entries` and `continuationToken`. * `entries` gives a list of containers and the `continuationToken` is used for the next listing operation. * `response` will contain information related to this operation. */ BlobService.prototype.listContainersSegmentedWithPrefix = function (prefix, currentToken, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('listContainers', function (v) { v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.get() .withQueryOption(QueryStringConstants.COMP, 'list') .withQueryOption(QueryStringConstants.MAX_RESULTS, options.maxResults) .withQueryOption(QueryStringConstants.INCLUDE, options.include); if (!azureutil.objectIsNull(currentToken)) { webResource.withQueryOption(QueryStringConstants.MARKER, currentToken.nextMarker); } webResource.withQueryOption(QueryStringConstants.PREFIX, prefix); options.requestLocationMode = azureutil.getNextListingLocationMode(currentToken); var processResponseCallback = function (responseObject, next) { responseObject.listContainersResult = null; if (!responseObject.error) { responseObject.listContainersResult = { entries: null, continuationToken: null }; responseObject.listContainersResult.entries = []; var containers = []; if (responseObject.response.body.EnumerationResults.Containers && responseObject.response.body.EnumerationResults.Containers.Container) { containers = responseObject.response.body.EnumerationResults.Containers.Container; if (!_.isArray(containers)) { containers = [ containers ]; } } containers.forEach(function (currentContainer) { var containerResult = ContainerResult.parse(currentContainer); responseObject.listContainersResult.entries.push(containerResult); }); if (responseObject.response.body.EnumerationResults.NextMarker) { responseObject.listContainersResult.continuationToken = { nextMarker: null, targetLocation: null }; responseObject.listContainersResult.continuationToken.nextMarker = responseObject.response.body.EnumerationResults.NextMarker; responseObject.listContainersResult.continuationToken.targetLocation = responseObject.targetLocation; } } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.listContainersResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; // Container methods /** * Checks whether or not a container exists on the service. * * @this {BlobService} * @param {string} container The container name. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will * be true if the container exists, or false if the container does not exist. * `response` will contain information related to this operation. */ BlobService.prototype.doesContainerExist = function (container, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('doesContainerExist', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); this._doesContainerExist(container, false, options, callback); }; /** * 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 request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @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 server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * the container information. * `response` will contain information related to this operation. */ BlobService.prototype.createContainer = function (container, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = 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 options = extend(true, {}, userOptions); var webResource = WebResource.put(container) .withQueryOption(QueryStringConstants.RESTYPE, 'container'); webResource.addOptionalMetadataHeaders(options.metadata); webResource.withHeader(HeaderConstants.BLOB_PUBLIC_ACCESS, 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.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 request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @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 server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will * 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-storage'); * 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 userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createContainerIfNotExists', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var self = this; self._doesContainerExist(container, true, options, function (error, exists, response) { if (error) { callback(error, exists, response); } else if (exists) { response.isSuccessful = true; callback(error, false, response); } else { self.createContainer(container, options, function (createError, responseContainer, createResponse) { var created; if (!createError) { created = true; } else if (createError && createError.statusCode === Constants.HttpConstants.HttpResponseCodes.Conflict && createError.code === Constants.BlobErrorCodeStrings.CONTAINER_ALREADY_EXISTS) { // If it was created before, there was no actual error. createError = null; created = false; createResponse.isSuccessful = true; } callback(createError, created, createResponse); }); } }); }; /** * 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 {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {string} [options.leaseId] The container lease identifier. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * information for the container. * `response` will contain information related to this operation. */ BlobService.prototype.getContainerProperties = function (container, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getContainerProperties', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.head(container) .withQueryOption(QueryStringConstants.RESTYPE, 'container') .withHeader(HeaderConstants.LEASE_ID, options.leaseId); options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY; 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 container lease identifier. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * information for the container. * `response` will contain information related to this operation. */ BlobService.prototype.getContainerMetadata = function (container, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getContainerMetadata', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.head(container) .withQueryOption(QueryStringConstants.RESTYPE, 'container') .withQueryOption(QueryStringConstants.COMP, 'metadata') .withHeader(HeaderConstants.LEASE_ID, options.leaseId); options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY; 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 request options. * @param {string} [options.leaseId] The container lease identifier. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {object} [options.accessConditions] See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} 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 userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('setContainerMetadata', function (v) { v.string(container, 'container'); v.object(metadata, 'metadata'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.put(container) .withQueryOption(QueryStringConstants.RESTYPE, 'container') .withQueryOption(QueryStringConstants.COMP, 'metadata') .withHeader(HeaderConstants.LEASE_ID, options.leaseId); webResource.addOptionalMetadataHeaders(metadata); var processResponseCallback = function (responseObject, next) { responseObject.containerResult = null; if (!responseObject.error) { responseObject.containerResult = new ContainerResult(container); 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); }; /** * Gets the container's ACL. * * @this {BlobService} * @param {string} container The container name. * @param {object} [options] The request options. * @param {string} [options.leaseId] The container lease identifier. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * information for the container. * `response` will contain information related to this operation. */ BlobService.prototype.getContainerAcl = function (container, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getContainerAcl', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.get(container) .withQueryOption(QueryStringConstants.RESTYPE, 'container') .withQueryOption(QueryStringConstants.COMP, 'acl') .withHeader(HeaderConstants.LEASE_ID, options.leaseId); options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY; 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 = AclResult.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 {object} signedIdentifiers The signed identifiers. Signed identifiers must be in an array. * @param {object} [options] The request options. * @param {string} [options.publicAccessLevel] Specifies whether data in the container may be accessed publicly and the level of access. * @param {string} [options.leaseId] The container lease identifier. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * information for the container. * `response` will contain information related to this operation. */ BlobService.prototype.setContainerAcl = function (container, signedIdentifiers, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('setContainerAcl', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var policies = null; if (signedIdentifiers) { if (!_.isArray(signedIdentifiers)) { throw new Error(SR.INVALID_SIGNED_IDENTIFIERS); } policies = AclResult.serialize(signedIdentifiers); } var webResource = WebResource.put(container) .withQueryOption(QueryStringConstants.RESTYPE, 'container') .withQueryOption(QueryStringConstants.COMP, 'acl') .withHeader(HeaderConstants.CONTENT_LENGTH, !azureutil.objectIsNull(policies) ? Buffer.byteLength(policies) : 0) .withHeader(HeaderConstants.BLOB_PUBLIC_ACCESS, options.publicAccessLevel) .withHeader(HeaderConstants.LEASE_ID, options.leaseId) .withBody(policies); var processResponseCallback = function (responseObject, next) { responseObject.containerResult = null; if (!responseObject.error) { responseObject.containerResult = new ContainerResult(container, options.publicAccessLevel); responseObject.containerResult.getPropertiesFromHeaders(responseObject.response.headers); if (signedIdentifiers) { responseObject.containerResult.signedIdentifiers = 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 request options. * @param {string} [options.leaseId] The container lease identifier. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} 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 userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('deleteContainer', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.del(container) .withQueryOption(QueryStringConstants.RESTYPE, 'container') .withHeader(HeaderConstants.LEASE_ID, 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); }; /** * Marks the specified container for deletion if it exists. * 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 request options. * @param {string} [options.leaseId] The container lease identifier. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will * be true if the container exists and was deleted, or false if the container * did not exist. * `response` will contain information related to this operation. */ BlobService.prototype.deleteContainerIfExists = function (container, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('deleteContainerIfExists', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var self = this; self._doesContainerExist(container, true, options, function (error, exists, response) { if (error) { callback(error, exists, response); } else if (!exists) { response.isSuccessful = true; callback(error, false, response); } else { self.deleteContainer(container, options, function (deleteError, deleteResponse) { var deleted; if (!deleteError) { deleted = true; } else if (deleteError && deleteError.statuscode === Constants.HttpConstants.HttpResponseCodes.NotFound && deleteError.code === Constants.BlobErrorCodeStrings.CONTAINER_NOT_FOUND) { // If it was deleted already, there was no actual error. deleted = false; deleteError = null; deleteResponse.isSuccessful = true; } callback(deleteError, deleted, deleteResponse); }); } }); }; /** * Lists a segment containing a collection of blob directory items in the container. * * @this {BlobService} * @param {string} container The container name. * @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation. * @param {object} [options] The request options. * @param {int} [options.maxResults] Specifies the maximum number of directories to return per call to Azure ServiceClient. This does NOT affect list size returned by this function. (maximum: 5000) * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain `entries` and `continuationToken`. * `entries` gives a list of directories and the `continuationToken` is used for the next listing operation. * `response` will contain information related to this operation. */ BlobService.prototype.listBlobDirectoriesSegmented = function (container, currentToken, optionsOrCallback, callback) { this.listBlobDirectoriesSegmentedWithPrefix(container, null /* prefix */, currentToken, optionsOrCallback, callback); }; /** * Lists a segment containing a collection of blob directory items in the container. * * @this {BlobService} * @param {string} container The container name. * @param {string} prefix The prefix of the blob directory. * @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation. * @param {object} [options] The request options. * @param {int} [options.maxResults] Specifies the maximum number of directories to return per call to Azure ServiceClient. This does NOT affect list size returned by this function. (maximum: 5000) * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain `entries` and `continuationToken`. * `entries` gives a list of directories and the `continuationToken` is used for the next listing operation. * `response` will contain information related to this operation. */ BlobService.prototype.listBlobDirectoriesSegmentedWithPrefix = function (container, prefix, currentToken, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); userOptions.delimiter = '/'; this._listBlobsOrDircotriesSegmentedWithPrefix(container, prefix, currentToken, BlobConstants.ListBlobTypes.Directory, userOptions, callback); }; /** * Lists a segment containing a collection of blob items in the container. * * @this {BlobService} * @param {string} container The container name. * @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation. * @param {object} [options] The request options. * @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.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 {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain `entries` and `continuationToken`. * `entries` gives a list of blobs and the `continuationToken` is used for the next listing operation. * `response` will contain information related to this operation. */ BlobService.prototype.listBlobsSegmented = function (container, currentToken, optionsOrCallback, callback) { this.listBlobsSegmentedWithPrefix(container, null /* prefix */, currentToken, optionsOrCallback, callback); }; /** * Lists a segment containing a collection of blob items whose names begin with the specified prefix in the container. * * @this {BlobService} * @param {string} container The container name. * @param {string} prefix The prefix of the blob name. * @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation. * @param {object} [options] The request options. * @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.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 {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs]The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * the entries of blobs and the continuation token for the next listing operation. * `response` will contain information related to this operation. */ BlobService.prototype.listBlobsSegmentedWithPrefix = function (container, prefix, currentToken, optionsOrCallback, callback) { this._listBlobsOrDircotriesSegmentedWithPrefix(container, prefix, currentToken, BlobConstants.ListBlobTypes.Blob, optionsOrCallback, callback); }; // Lease methods /** * Acquires a new lease. If container and blob are specified, acquires a blob lease. Otherwise, if only container is specified and blob is null, acquires a container lease. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {string} [options.leaseDuration] The lease duration in seconds. A non-infinite lease can be between 15 and 60 seconds. Default is never to expire. * @param {string} [options.proposedLeaseId] The proposed lease identifier. Must be a GUID. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * the lease information. * `response` will contain information related to this operation. */ BlobService.prototype.acquireLease = function (container, blob, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('acquireLease', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); if (!options.leaseDuration) { options.leaseDuration = -1; } this._leaseImpl(container, blob, null /* leaseId */, BlobConstants.LeaseOperation.ACQUIRE, options, callback); }; /** * Renews an existing lease. If container and blob are specified, renews the blob lease. Otherwise, if only container is specified and blob is null, renews the container lease. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {string} leaseId The lease identifier. Must be a GUID. * @param {object} [options] The request options. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * the lease information. * `response` will contain information related to this operation. */ BlobService.prototype.renewLease = function (container, blob, leaseId, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('renewLease', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); this._leaseImpl(container, blob, leaseId, BlobConstants.LeaseOperation.RENEW, options, callback); }; /** * Changes the lease ID of an active lease. If container and blob are specified, changes the blob lease. Otherwise, if only container is specified and blob is null, changes the * container lease. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {string} leaseId The current lease identifier. * @param {string} proposedLeaseId The proposed lease identifier. Must be a GUID. * @param {object} [options] The request options. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the lease information. * `response` will contain information related to this operation. */ BlobService.prototype.changeLease = function (container, blob, leaseId, proposedLeaseId, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('changeLease', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); options.proposedLeaseId = proposedLeaseId; this._leaseImpl(container, blob, leaseId, BlobConstants.LeaseOperation.CHANGE, options, callback); }; /** * Releases the lease. If container and blob are specified, releases the blob lease. Otherwise, if only container is specified and blob is null, releases the container lease. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {string} leaseId The lease identifier. * @param {object} [options] The request options. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * the lease information. * `response` will contain information related to this operation. */ BlobService.prototype.releaseLease = function (container, blob, leaseId, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('releaseLease', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); this._leaseImpl(container, blob, leaseId, BlobConstants.LeaseOperation.RELEASE, options, callback); }; /** * Breaks the lease but ensures that another client cannot acquire a new lease until the current lease period has expired. If container and blob are specified, breaks the blob lease. * Otherwise, if only container is specified and blob is null, breaks the container lease. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {int} [options.leaseBreakPeriod] The lease break period, between 0 and 60 seconds. If unspecified, a fixed-duration lease breaks after * the remaining lease period elapses, and an infinite lease breaks immediately. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * the lease information. * `response` will contain information related to this operation. */ BlobService.prototype.breakLease = function (container, blob, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('breakLease', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); this._leaseImpl(container, blob, null /*leaseId*/, BlobConstants.LeaseOperation.BREAK, options, callback); }; // Blob methods /** * Returns all user-defined metadata, standard HTTP properties, and system properties for the blob. * It does not return or modify the content of the blob. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {string} [options.snapshotId] The snapshot identifier. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * information about the blob. * `response` will contain information related to this operation. */ BlobService.prototype.getBlobProperties = function (container, blob, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getBlobProperties', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(container, blob); var webResource = WebResource.head(resourceName); if (options.snapshotId) { webResource.withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId); } BlobResult.setHeadersFromBlob(webResource, options); options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY; var self = this; var processResponseCallback = function (responseObject, next) { responseObject.blobResult = null; if (!responseObject.error) { responseObject.blobResult = new BlobResult(container, blob); responseObject.blobResult.metadata = self.parseMetadataHeaders(responseObject.response.headers); responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.blobResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Returns all user-defined metadata for the specified blob or snapshot. * It does not modify or return the content of the blob. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {string} [options.snapshotId] The snapshot identifier. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * information about the blob. * `response` will contain information related to this operation. */ BlobService.prototype.getBlobMetadata = function (container, blob, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getBlobMetadata', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(container, blob); var webResource = WebResource.head(resourceName); webResource.withQueryOption(QueryStringConstants.COMP, 'metadata'); webResource.withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId); BlobResult.setHeadersFromBlob(webResource, options); options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY; var self = this; var processResponseCallback = function (responseObject, next) { responseObject.blobResult = null; if (!responseObject.error) { responseObject.blobResult = new BlobResult(container, blob); responseObject.blobResult.metadata = self.parseMetadataHeaders(responseObject.response.headers); responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.blobResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Sets user-defined properties for the specified blob or snapshot. * It does not modify or return the content of the blob. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [properties] The blob properties to set. * @param {string} [properties.contentType] The MIME content type of the blob. The default type is application/octet-stream. * @param {string} [properties.contentEncoding] The content encodings that have been applied to the blob. * @param {string} [properties.contentLanguage] The natural languages used by this resource. * @param {string} [properties.contentMD5] The MD5 hash of the blob content. * @param {string} [properties.cacheControl] The blob's cache control. * @param {string} [properties.contentDisposition] The blob's content disposition. (x-ms-blob-content-disposition) * @param {object} [options] The request options. * @param {string} [options.leaseId] The lease identifier. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @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 server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * information about the blob. * `response` will contain information related to this operation. */ BlobService.prototype.setBlobProperties = function (container, blob, properties, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('setBlobProperties', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, properties, userOptions); var resourceName = createResourceName(container, blob); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.COMP, 'properties'); BlobResult.setPropertiesFromBlob(webResource, options); this._setBlobPropertiesHelper({ webResource: webResource, options: options, container: container, blob: blob, callback: callback }); }; /** * Sets user-defined metadata for the specified blob or snapshot as one or more name-value pairs * It does not modify or return the content of the blob. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} metadata The metadata key/value pairs. * @param {object} [options] The request options. * @param {string} [options.snapshotId] The snapshot identifier. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * information on the blob. * `response` will contain information related to this operation. */ BlobService.prototype.setBlobMetadata = function (container, blob, metadata, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('setBlobMetadata', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.object(metadata, 'metadata'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(container, blob); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.COMP, 'metadata'); webResource.withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId); options.metadata = metadata; BlobResult.setHeadersFromBlob(webResource, options); var processResponseCallback = function (responseObject, next) { responseObject.blobResult = null; if (!responseObject.error) { responseObject.blobResult = new BlobResult(container, blob); responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.blobResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Downloads a blob into a file. * * @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 downloaded. * @param {object} [options] The request options. * @param {boolean} [options.skipSizeCheck] Skip the size check to perform direct download. * Set the option to true for small blobs. * Parallel download and speed summary won't work with this option on. * @param {SpeedSummary} [options.speedSummary] The download tracker objects. * @param {int} [options.parallelOperationThreadCount] Parallel operation thread count * @param {string} [options.snapshotId] The snapshot identifier. * @param {string} [options.leaseId] The lease identifier. * @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range. * @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions. * @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the blob information. * `response` will contain information related to this operation. * @return {SpeedSummary} * * @example * var azure = require('azure-storage'); * var blobService = azure.createBlobService(); * blobService.getBlobToLocalFile('taskcontainer', 'task1', 'task1-download.txt', function(error, serverBlob) { * if(!error) { * // Blob available in serverBlob.blob variable * } */ BlobService.prototype.getBlobToLocalFile = function (container, blob, localFileName, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('getBlobToLocalFile', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.string(localFileName, 'localFileName'); v.containerNameIsValid(container); v.callback(callback); }); return this._getBlobToLocalFile(container, blob, localFileName, options, callback); }; /** * Provides a stream to read from a blob. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {string} [options.snapshotId] The snapshot identifier. * @param {string} [options.leaseId] The lease identifier. * @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range. * @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions. * @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the blob information. * `response` will contain information related to this operation. * @return {Stream} * @example * var azure = require('azure-storage'); * var blobService = azure.createBlobService(); * var writable = fs.createWriteStream(destinationFileNameTarget); * blobService.createReadStream(containerName, blobName).pipe(writable); */ BlobService.prototype.createReadStream = function (container, blob, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('createReadStream', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); }); var readStream = new ChunkStream(); this.getBlobToStream(container, blob, readStream, options, function (error, responseBlob, response) { if (error) { readStream.emit('error', error); } if (callback) { callback(error, responseBlob, response); } }); return readStream; }; /** * Downloads a blob into a stream. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {Stream} writeStream The write stream. * @param {object} [options] The request options. * @param {boolean} [options.skipSizeCheck] Skip the size check to perform direct download. * Set the option to true for small blobs. * Parallel download and speed summary won't work with this option on. * @param {SpeedSummary} [options.speedSummary] The download tracker objects. * @param {string} [options.snapshotId] The snapshot identifier. * @param {string} [options.leaseId] The lease identifier. * @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range. * @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range. * @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions. * @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the blob information. * `response` will contain information related to this operation. * @return {SpeedSummary} * * @example * var azure = require('azure-storage'); * var blobService = azure.createBlobService(); * blobService.getBlobToStream('taskcontainer', 'task1', fs.createWriteStream('task1-download.txt'), function(error, serverBlob) { * if(!error) { * // Blob available in serverBlob.blob variable * } * }); */ BlobService.prototype.getBlobToStream = function (container, blob, writeStream, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); userOptions.speedSummary = userOptions.speedSummary || new SpeedSummary(blob); validate.validateArgs('getBlobToStream', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.object(writeStream, 'writeStream'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var propertiesRequestOptions = { timeoutIntervalInMs : options.timeoutIntervalInMs, snapshotId : options.snapshotId, accessConditions : options.accessConditions }; if (options.skipSizeCheck) { this._getBlobToStream(container, blob, writeStream, options, callback); } else { var self = this; this.getBlobProperties(container, blob, propertiesRequestOptions, function (error, properties) { if (error) { callback(error); } else { var size; if (options.rangeStart) { var endOffset = properties.contentLength - 1; var end = options.rangeEnd ? Math.min(options.rangeEnd, endOffset) : endOffset; size = end - options.rangeStart + 1; } else { size = properties.contentLength; } options.speedSummary.totalSize = size; if (size > self.singleBlobPutThresholdInBytes) { options.contentMD5 = properties.contentMD5; self._getBlobToRangeStream(container, blob, properties.blobType, writeStream, options, callback); } else { self._getBlobToStream(container, blob, writeStream, options, callback); } } }); } return options.speedSummary; }; /** * Downloads a blob into a text string. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {string} [options.snapshotId] The snapshot identifier. * @param {string} [options.leaseId] The lease identifier. * @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range. * @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range. * @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {BlobService~blobToText} callback `error` will contain information * if an error occurs; otherwise `text` will contain the blob contents, * and `blockBlob` will contain * the blob information. * `response` will contain information related to this operation. */ BlobService.prototype.getBlobToText = function (container, blob, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getBlobToText', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(container, blob); var webResource = WebResource.get(resourceName) .withRawResponse(); webResource.withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId); BlobResult.setHeadersFromBlob(webResource, options); options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY; var self = this; var processResponseCallback = function (responseObject, next) { responseObject.text = null; responseObject.blobResult = null; if (!responseObject.error) { responseObject.blobResult = new BlobResult(container, blob); responseObject.blobResult.metadata = self.parseMetadataHeaders(responseObject.response.headers); responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers); responseObject.text = responseObject.response.body; self._validateLengthAndMD5(options, responseObject); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.text, returnObject.blobResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection. * If a blob has snapshots, you must delete them when deleting the blob. Using the deleteSnapshots option, you can choose either to delete both the blob and its snapshots, * or to delete only the snapshots but not the blob itself. If the blob has snapshots, you must include the deleteSnapshots option or the blob service will return an error * and nothing will be deleted. * If you are deleting a specific snapshot using the snapshotId option, the deleteSnapshots option must NOT be included. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {string} [options.deleteSnapshots] The snapshot delete option. See azure.BlobUtilities.SnapshotDeleteOptions.*. * @param {string} [options.snapshotId] The snapshot identifier. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback `error` will contain information * if an error occurs; `response` will contain information related to this operation. */ BlobService.prototype.deleteBlob = function (container, blob, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('deleteBlob', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(container, blob); var webResource = WebResource.del(resourceName) .withHeader(HeaderConstants.LEASE_ID, options.leaseId); if (!azureutil.objectIsNull(options.snapshotId) && !azureutil.objectIsNull(options.deleteSnapshots)) { throw new Error(SR.INVALID_DELETE_SNAPSHOT_OPTION); } webResource.withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId); webResource.withHeader(HeaderConstants.DELETE_SNAPSHOT, options.deleteSnapshots); BlobResult.setHeadersFromBlob(webResource, options); var processResponseCallback = function (responseObject, next) { var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Checks whether or not a blob exists on the service. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `errorOrResult` will * be true if the blob exists, or false if the blob does not exist. * `response` will contain information related to this operation. */ BlobService.prototype.doesBlobExist = function (container, blob, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('doesBlobExist', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); this._doesBlobExist(container, blob, false, options, callback); }; /** * Marks the specified blob or snapshot for deletion if it exists. The blob is later deleted during garbage collection. * If a blob has snapshots, you must delete them when deleting the blob. Using the deleteSnapshots option, you can choose either to delete both the blob and its snapshots, * or to delete only the snapshots but not the blob itself. If the blob has snapshots, you must include the deleteSnapshots option or the blob service will return an error * and nothing will be deleted. * If you are deleting a specific snapshot using the snapshotId option, the deleteSnapshots option must NOT be included. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {string} [options.deleteSnapshots] The snapshot delete option. See azure.BlobUtilities.SnapshotDeleteOptions.*. * @param {string} [options.snapshotId] The snapshot identifier. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will * be true if the blob was deleted, or false if the blob * does not exist. * `response` will contain information related to this operation. */ BlobService.prototype.deleteBlobIfExists = function (container, blob, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('deleteBlobIfExists', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var self = this; self._doesBlobExist(container, blob, true, options, function (error, exists, response) { if (error) { callback(error, exists, response); } else if (!exists) { response.isSuccessful = true; callback(error, false, response); } else { self.deleteBlob(container, blob, options, function (deleteError, deleteResponse) { var deleted; if (!deleteError) { deleted = true; } else if (deleteError && deleteError.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound && deleteError.code === Constants.BlobErrorCodeStrings.BLOB_NOT_FOUND) { // If it was deleted already, there was no actual error. deleted = false; deleteError = null; deleteResponse.isSuccessful = true; } callback(deleteError, deleted, deleteResponse); }); } }); }; /** * Creates a read-only snapshot of a blob. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {string} [options.snapshotId] The snapshot identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * the ID of the snapshot. * `response` will contain information related to this operation. */ BlobService.prototype.createBlobSnapshot = function (container, blob, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createBlobSnapshot', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(container, blob); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.COMP, 'snapshot'); BlobResult.setHeadersFromBlob(webResource, options); var processResponseCallback = function (responseObject, next) { responseObject.snapshotId = null; if (!responseObject.error) { responseObject.snapshotId = responseObject.response.headers[HeaderConstants.SNAPSHOT]; } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.snapshotId, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Starts to copy a blob to a destination within the storage account. The Copy Blob operation copies the entire committed blob. * * @this {BlobService} * @param {string} sourceUri The source blob URI. * @param {string} targetContainer The target container name. * @param {string} targetBlob The target blob name. * @param {object} [options] The request options. * @param {string} [options.snapshotId] The source blob snapshot identifier. * @param {object} [options.metadata] The target blob metadata key/value pairs. * @param {string} [options.leaseId] The target blob lease identifier. * @param {string} [options.sourceLeaseId] The source blob lease identifier. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {object} [options.sourceAccessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * the blob information. * `response` will contain information related to this operation. */ BlobService.prototype.startCopyBlob = function (sourceUri, targetContainer, targetBlob, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('startCopyBlob', function (v) { v.string(sourceUri, 'sourceUri'); v.string(targetContainer, 'targetContainer'); v.string(targetBlob, 'targetBlob'); v.containerNameIsValid(targetContainer); v.callback(callback); }); var targetResourceName = createResourceName(targetContainer, targetBlob); var options = extend(true, {}, userOptions); if (options.snapshotId) { sourceUri += '?snapshot=' + options.snapshotId; } var webResource = WebResource.put(targetResourceName) .withHeader(HeaderConstants.COPY_SOURCE, sourceUri); webResource.withHeader(HeaderConstants.LEASE_ID, options.leaseId); webResource.withHeader(HeaderConstants.SOURCE_LEASE_ID, options.sourceLeaseId); webResource.addOptionalMetadataHeaders(options.metadata); var processResponseCallback = function (responseObject, next) { responseObject.blobResult = null; if (!responseObject.error) { responseObject.blobResult = new BlobResult(targetContainer, targetBlob); responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers); if (options.metadata) { responseObject.blobResult.metadata = options.metadata; } } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.blobResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Abort a blob copy operation. * * @this {BlobService} * @param {string} container The destination container name. * @param {string} blob The destination blob name. * @param {string} copyId The copy operation identifier. * @param {object} [options] The request options. * @param {string} [options.leaseId] The target blob lease identifier. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * the blob information. * `response` will contain information related to this operation. */ BlobService.prototype.abortCopyBlob = function (container, blob, copyId, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('abortCopyBlob', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var resourceName = createResourceName(container, blob); var options = extend(true, {}, userOptions); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.COPY_ID, copyId) .withQueryOption(QueryStringConstants.COMP, 'copy') .withHeader(HeaderConstants.COPY_ACTION, 'abort'); webResource.withHeader(HeaderConstants.LEASE_ID, 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); }; /** * Retrieves a shared access signature token. * * @this {BlobService} * @param {string} container The container name. * @param {string} [blob] The blob name. * @param {object} sharedAccessPolicy The shared access policy. * @param {string} [sharedAccessPolicy.Id] The signed identifier. * @param {object} [sharedAccessPolicy.AccessPolicy.Permissions] The permission type. * @param {date|string} [sharedAccessPolicy.AccessPolicy.Start] The time at which the Shared Access Signature becomes valid (The UTC value will be used). * @param {date|string} [sharedAccessPolicy.AccessPolicy.Expiry] The time at which the Shared Access Signature becomes expired (The UTC value will be used). * @param {string} [sharedAccessPolicy.AccessPolicy.IPAddressOrRange] An IP address or a range of IP addresses from which to accept requests. When specifying a range, note that the range is inclusive. * @param {string} [sharedAccessPolicy.AccessPolicy.Protocol] The protocol permitted for a request made with the account SAS. * Possible values are both HTTPS and HTTP (https,http) or HTTPS only (https). The default value is https,http. * @param {object} [headers] The optional header values to set for a blob returned wth this SAS. * @param {string} [headers.cacheControl] The optional value of the Cache-Control response header to be returned when this SAS is used. * @param {string} [headers.contentType] The optional value of the Content-Type response header to be returned when this SAS is used. * @param {string} [headers.contentEncoding] The optional value of the Content-Encoding response header to be returned when this SAS is used. * @param {string} [headers.contentLanguage] The optional value of the Content-Language response header to be returned when this SAS is used. * @param {string} [headers.contentDisposition] The optional value of the Content-Disposition response header to be returned when this SAS is used. * @return {string} The shared access signature query string. Note this string does not contain the leading "?". */ BlobService.prototype.generateSharedAccessSignature = function (container, blob, sharedAccessPolicy, headers) { // check if the BlobService is able to generate a shared access signature if (!this.storageCredentials || !this.storageCredentials.generateSignedQueryString) { throw new Error(SR.CANNOT_CREATE_SAS_WITHOUT_ACCOUNT_KEY); } // Validate container name. Blob name is optional. validate.validateArgs('generateSharedAccessSignature', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.object(sharedAccessPolicy, 'sharedAccessPolicy'); }); var resourceType = BlobConstants.ResourceTypes.CONTAINER; if (blob) { validate.validateArgs('generateSharedAccessSignature', function (v) { v.string(blob, 'blob'); }); resourceType = BlobConstants.ResourceTypes.BLOB; } if (sharedAccessPolicy.AccessPolicy) { if (!azureutil.objectIsNull(sharedAccessPolicy.AccessPolicy.Start)) { if (!_.isDate(sharedAccessPolicy.AccessPolicy.Start)) { sharedAccessPolicy.AccessPolicy.Start = new Date(sharedAccessPolicy.AccessPolicy.Start); } sharedAccessPolicy.AccessPolicy.Start = azureutil.truncatedISO8061Date(sharedAccessPolicy.AccessPolicy.Start); } if (!azureutil.objectIsNull(sharedAccessPolicy.AccessPolicy.Expiry)) { if (!_.isDate(sharedAccessPolicy.AccessPolicy.Expiry)) { sharedAccessPolicy.AccessPolicy.Expiry = new Date(sharedAccessPolicy.AccessPolicy.Expiry); } sharedAccessPolicy.AccessPolicy.Expiry = azureutil.truncatedISO8061Date(sharedAccessPolicy.AccessPolicy.Expiry); } } var resourceName = createResourceName(container, blob, true); return this.storageCredentials.generateSignedQueryString(Constants.ServiceType.Blob, resourceName, sharedAccessPolicy, null, { headers: headers, resourceType: resourceType }); }; /** * Retrieves a blob or container URL. * * @param {string} container The container name. * @param {string} [blob] The blob name. * @param {string} [sasToken] The Shared Access Signature token. * @param {boolean} [primary] A boolean representing whether to use the primary or the secondary endpoint. * @return {string} The formatted URL string. * @example * var azure = require('azure-storage'); * var blobService = azure.createBlobService(); * //create a SAS that expires in an hour * var sasToken = blobService.generateSharedAccessSignature(containerName, blobName, { AccessPolicy: { Expiry: azure.date.minutesFromNow(60); } }); * var sasUrl = blobService.getUrl(containerName, blobName, sasToken, true); */ BlobService.prototype.getUrl = function (container, blob, sasToken, primary) { validate.validateArgs('getUrl', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); }); var host; if (!azureutil.objectIsNull(primary) && primary === false) { host = this.host.secondaryHost; } else { host = this.host.primaryHost; } host = azureutil.trimPortFromUri(host); return url.resolve(host, url.format({ pathname: this._getPath('/' + createResourceName(container, blob)), query: qs.parse(sasToken) })); }; // Page blob methods /** * Creates a page blob of the specified length. If the blob already exists on the service, it will be overwritten. * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object. * * @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 request options. * @param {object} [options.metadata] The metadata key/value pairs. * @param {string} [options.leaseId] The target blob lease identifier. * @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.contentDisposition] The blob's content disposition. (x-ms-blob-content-disposition) * @param {string} [options.sequenceNumber] The blob's sequence number. (x-ms-blob-sequence-number) * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} 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 userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createPageBlob', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.value(length, 'length'); v.callback(callback); }); if (length && length % BlobConstants.PAGE_SIZE !== 0) { throw new Error(SR.INVALID_PAGE_BLOB_LENGTH); } var options = extend(true, {}, userOptions); var resourceName = createResourceName(container, blob); var webResource = WebResource.put(resourceName) .withHeader(HeaderConstants.BLOB_TYPE, BlobConstants.BlobTypes.PAGE) .withHeader(HeaderConstants.BLOB_CONTENT_LENGTH, length) .withHeader(HeaderConstants.CONTENT_LENGTH, 0) .withHeader(HeaderConstants.LEASE_ID, options.leaseId); BlobResult.setHeadersFromBlob(webResource, options); var processResponseCallback = function (responseObject, next) { var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Uploads a page blob from file. If the blob already exists on the service, it will be overwritten. * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object. * * @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 request options. * @param {SpeedSummary} [options.speedSummary] The upload tracker objects. * @param {int} [options.parallelOperationThreadCount] Parallel operation thread count * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. * The default value is false for page blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.contentDisposition] The blob's content disposition. (x-ms-blob-content-disposition) * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback The callback function. * @return {SpeedSummary} */ BlobService.prototype.createPageBlobFromLocalFile = function (container, blob, localFileName, optionsOrCallback, callback) { return this._createBlobFromLocalFile(container, blob, BlobConstants.BlobTypes.PAGE, localFileName, optionsOrCallback, callback); }; /** * Uploads a page blob from a stream. If the blob already exists on the service, it will be overwritten. * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object. * * @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 request options. * @param {SpeedSummary} [options.speedSummary] The download tracker objects; * @param {int} [options.parallelOperationThreadCount] Parallel operation thread count * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. * The default value is false for page blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.contentDisposition] The blob's content disposition. (x-ms-blob-content-disposition) * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback The callback function. * @return {SpeedSummary} */ BlobService.prototype.createPageBlobFromStream = function (container, blob, stream, streamLength, optionsOrCallback, callback) { return this._createBlobFromStream(container, blob, BlobConstants.BlobTypes.PAGE, stream, streamLength, optionsOrCallback, callback); }; /** * Provides a stream to write to a page blob. Assumes that the blob exists. * If it does not, please create the blob using createPageBlob before calling this method or use createWriteStreamNewPageBlob. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {int} [options.parallelOperationThreadCount] Parallel operation thread count * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. * The default value is false for page blobs and true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.contentDisposition] The blob's content disposition. (x-ms-blob-content-disposition) * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback The callback function. * @return {Stream} * @example * var azure = require('azure-storage'); * var blobService = azure.createBlobService(); * blobService.createPageBlob(containerName, blobName, 1024, function (err) { * // Pipe file to a blob * var stream = fs.createReadStream(fileNameTarget).pipe(blobService.createWriteStreamToExistingPageBlob(containerName, blobName)); * }); */ BlobService.prototype.createWriteStreamToExistingPageBlob = function (container, blob, optionsOrCallback, callback) { return this._createWriteStreamToBlob(container, blob, BlobConstants.BlobTypes.PAGE, 0, false, optionsOrCallback, callback); }; /** * Provides a stream to write to a page blob. Creates the blob before writing data. If the blob already exists on the service, it will be overwritten. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {string} length The blob length. * @param {object} [options] The request options. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {int} [options.parallelOperationThreadCount] Parallel operation thread count * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. * The default value is false for page blobs and true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.contentDisposition] The blob's content disposition. (x-ms-blob-content-disposition) * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback The callback function. * @return {Stream} * @example * var azure = require('azure-storage'); * var blobService = azure.createBlobService(); * blobService.createPageBlob(containerName, blobName, 1024, function (err) { * // Pipe file to a blob * var stream = fs.createReadStream(fileNameTarget).pipe(blobService.createWriteStreamToNewPageBlob(containerName, blobName)); * }); */ BlobService.prototype.createWriteStreamToNewPageBlob = function (container, blob, length, optionsOrCallback, callback) { return this._createWriteStreamToBlob(container, blob, BlobConstants.BlobTypes.PAGE, length, true, optionsOrCallback, callback); }; /** * Updates a page blob from a stream. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {Stream} readStream The read stream. * @param {int} rangeStart The range start. * @param {int} rangeEnd The range end. * @param {object} [options] The request options. * @param {string} [options.leaseId] The target blob lease identifier. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @param {string} [options.contentMD5] An optional hash value used to ensure transactional integrity for the page. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * the blob information. * `response` will contain information related to this operation. */ BlobService.prototype.createPagesFromStream = function (container, blob, readStream, rangeStart, rangeEnd, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createPagesFromStream', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); if ((rangeEnd - rangeStart) + 1 > BlobConstants.MAX_UPDATE_PAGE_SIZE) { throw new Error(SR.INVALID_PAGE_RANGE_FOR_UPDATE); } var self = this; if (azureutil.objectIsNull(options.contentMD5) && options.useTransactionalMD5) { azureutil.calculateMD5(readStream, BlobConstants.MAX_UPDATE_PAGE_SIZE, options, function (internalBuff) { self._createPages(container, blob, internalBuff, null /* stream */, rangeStart, rangeEnd, options, callback); }); } else { self._createPages(container, blob, null /* text */, readStream, rangeStart, rangeEnd, options, callback); } }; /** * Lists page ranges. Lists all of the page ranges by default, or only the page ranges over a specific range of bytes if rangeStart and rangeEnd are specified. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {int} [options.rangeStart] The range start. * @param {int} [options.rangeEnd] The range end. * @param {string} [options.snapshotId] The snapshot identifier. * @param {string} [options.leaseId] The target blob lease identifier. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * the page range information. * `response` will contain information related to this operation. */ BlobService.prototype.listPageRanges = function (container, blob, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('listPageRanges', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(container, blob); var webResource = WebResource.get(resourceName) .withQueryOption(QueryStringConstants.COMP, 'pagelist') .withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId); if (options.rangeStart && options.rangeStart % BlobConstants.PAGE_SIZE !== 0) { throw new Error(SR.INVALID_PAGE_START_OFFSET); } if (options.rangeEnd && (options.rangeEnd + 1) % BlobConstants.PAGE_SIZE !== 0) { throw new Error(SR.INVALID_PAGE_END_OFFSET); } BlobResult.setHeadersFromBlob(webResource, options); options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY; var processResponseCallback = function (responseObject, next) { responseObject.pageRanges = null; if (!responseObject.error) { responseObject.pageRanges = []; var pageRanges = []; if (responseObject.response.body.PageList.PageRange) { pageRanges = responseObject.response.body.PageList.PageRange; if (!_.isArray(pageRanges)) { pageRanges = [ pageRanges ]; } } pageRanges.forEach(function (pageRange) { var range = { start: parseInt(pageRange.Start, 10), end: parseInt(pageRange.End, 10) }; responseObject.pageRanges.push(range); }); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.pageRanges, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Clears a range of pages. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {int} rangeStart The range start. * @param {int} rangeEnd The range end. * @param {object} [options] The request options. * @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 {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback `error` will contain information * if an error occurs; otherwise * `response` will contain information related to this operation. */ BlobService.prototype.clearPageRange = function (container, blob, rangeStart, rangeEnd, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('clearPageRange', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var request = this._updatePageBlobPagesImpl(container, blob, rangeStart, rangeEnd, BlobConstants.PageWriteOptions.CLEAR, options); var self = this; var processResponseCallback = function (responseObject, next) { var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.response); }; next(responseObject, finalCallback); }; self.performRequest(request, null, options, processResponseCallback); }; /** * Resizes a page blob. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {String} size The size of the page blob, in bytes. * @param {object} [options] The request options. * @param {string} [options.leaseId] The blob lease identifier. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * information about the blob. * `response` will contain information related to this operation. */ BlobService.prototype.resizePageBlob = function (container, blob, size, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('resizePageBlob', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(container, blob); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.COMP, 'properties'); if (size && size % BlobConstants.PAGE_SIZE !== 0) { throw new Error(SR.INVALID_PAGE_BLOB_LENGTH); } webResource.withHeader(HeaderConstants.BLOB_CONTENT_LENGTH, size); this._setBlobPropertiesHelper({ webResource: webResource, options: options, container: container, blob: blob, callback: callback }); }; /** * Sets the page blob's sequence number. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {SequenceNumberAction} sequenceNumberAction A value indicating the operation to perform on the sequence number. * The allowed values are defined in azure.BlobUtilities.SequenceNumberAction. * @param {string} sequenceNumber The sequence number. The value of the sequence number must be between 0 and 2^63 - 1. * Set this parameter to null if this operation is an increment action. * @param {object} [options] The request options. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * information about the blob. * `response` will contain information related to this operation. */ BlobService.prototype.setPageBlobSequenceNumber = function (container, blob, sequenceNumberAction, sequenceNumber, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('setPageBlobSequenceNumber', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); if (sequenceNumberAction === BlobUtilities.SequenceNumberAction.INCREMENT) { if (!azureutil.objectIsNull(sequenceNumber)) { throw new Error(SR.BLOB_INVALID_SEQUENCE_NUMBER); } } else { if (azureutil.objectIsNull(sequenceNumber)) { throw new Error(util.format(SR.ARGUMENT_NULL_OR_EMPTY, 'sequenceNumber')); } } var options = extend(true, {}, userOptions); var resourceName = createResourceName(container, blob); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.COMP, 'properties') .withHeader(HeaderConstants.SEQUENCE_NUMBER_ACTION, sequenceNumberAction); if (sequenceNumberAction !== BlobUtilities.SequenceNumberAction.INCREMENT) { webResource.withHeader(HeaderConstants.SEQUENCE_NUMBER, sequenceNumber); } var processResponseCallback = function (responseObject, next) { responseObject.blobResult = null; if (!responseObject.error) { responseObject.blobResult = new BlobResult(container, blob); responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.blobResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; // Block blob methods /** * Creates a new block blob. If the blob already exists on the service, it will be overwritten. * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object. * * @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 request options. * @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {int} [options.parallelOperationThreadCount] Parallel operation thread count * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback The callback function. * @return {SpeedSummary} */ BlobService.prototype.createBlockBlobFromLocalFile = function (container, blob, localFileName, optionsOrCallback, callback) { return this._createBlobFromLocalFile(container, blob, BlobConstants.BlobTypes.BLOCK, localFileName, optionsOrCallback, callback); }; /** * Uploads a block blob from a stream. If the blob already exists on the service, it will be overwritten. * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object. * * @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 request options. * @param {SpeedSummary} [options.speedSummary] The download tracker objects. * @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {int} [options.parallelOperationThreadCount] Parallel operation thread count * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback The callback function. * @return {SpeedSummary} */ BlobService.prototype.createBlockBlobFromStream = function (container, blob, stream, streamLength, optionsOrCallback, callback) { return this._createBlobFromStream(container, blob, BlobConstants.BlobTypes.BLOCK, stream, streamLength, optionsOrCallback, callback); }; /** * Uploads a block blob from a text string. If the blob already exists on the service, it will be overwritten. * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {string|object} text The blob text, as a string or in a Buffer. * @param {object} [options] The request options. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * information about the blob. * `response` will contain information related to this operation. * @return {undefined} */ BlobService.prototype.createBlockBlobFromText = function (container, blob, text, optionsOrCallback, callback) { return this._createBlobFromText(container, blob, BlobConstants.BlobTypes.BLOCK, text, optionsOrCallback, callback); }; /** * Provides a stream to write to a block blob. If the blob already exists on the service, it will be overwritten. * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {int} [options.parallelOperationThreadCount] Parallel operation thread count * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. * The default value is false for page blobs and true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.position] The blob's content disposition. (x-ms-blob-content-disposition) * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback The callback function. * @return {Stream} * @example * var azure = require('azure-storage'); * var blobService = azure.createBlobService(); * var stream = fs.createReadStream(fileNameTarget).pipe(blobService.createWriteStreamToBlockBlob(containerName, blobName, { blockIdPrefix: 'block' })); */ BlobService.prototype.createWriteStreamToBlockBlob = function (container, blob, optionsOrCallback, callback) { return this._createWriteStreamToBlob(container, blob, BlobConstants.BlobTypes.BLOCK, 0, false, optionsOrCallback, callback); }; /** * Creates a new block to be committed as part of a blob. * * @this {BlobService} * @param {string} blockId The block identifier. * @param {string} container The container name. * @param {string} blob The blob name. * @param {Stream} readStream The read stream. * @param {int} streamLength The stream length. * @param {object} [options] The request options. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @param {string} [options.leaseId] The target blob lease identifier. * @param {string} [options.contentMD5] The blob’s MD5 hash. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback `error` will contain information * if an error occurs; otherwise * `response` will contain information related to this operation. */ BlobService.prototype.createBlockFromStream = function (blockId, container, blob, readStream, streamLength, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createBlockFromStream', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.exists(readStream, 'readStream'); v.value(streamLength, 'streamLength'); v.callback(callback); }); var options = extend(true, {}, userOptions); if (streamLength > BlobConstants.MAX_BLOCK_SIZE) { throw new Error(SR.INVALID_STREAM_LENGTH); } else { this._createBlock(blockId, container, blob, null, readStream, streamLength, options, callback); } }; /** * Creates a new block to be committed as part of a blob. * * @this {BlobService} * @param {string} blockId The block identifier. * @param {string} container The container name. * @param {string} blob The blob name. * @param {string|buffer} content The block content. * @param {object} [options] The request options. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @param {string} [options.leaseId] The target blob lease identifier. * @param {string} [options.contentMD5] The blob’s MD5 hash. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback `error` will contain information * if an error occurs; otherwise * `response` will contain information related to this operation. * @return {undefined} */ BlobService.prototype.createBlockFromText = function (blockId, container, blob, content, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createBlockFromText', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var contentLength = (Buffer.isBuffer(content) ? content.length : Buffer.byteLength(content)); if (contentLength > BlobConstants.MAX_BLOCK_SIZE) { throw new Error(SR.INVALID_TEXT_LENGTH); } else { this._createBlock(blockId, container, blob, content, null, contentLength, options, callback); } }; /** * Creates a new block to be committed as part of a block blob. * @ignore * * @this {BlobService} * @param {string} blockId The block identifier. * @param {string} container The container name. * @param {string} blob The blob name. * @param {string|buffer} content The block content. * @param (Stream) stream The stream to the data to store. * @param {int} length The length of the stream or text to upload. * @param {object} [options] The request options. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @param {string} [options.leaseId] The target blob lease identifier. * @param {string} [options.contentMD5] The blob’s MD5 hash. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback `error` will contain information * if an error occurs; otherwise * `response` will contain information related to this operation. * @return {undefined} */ BlobService.prototype._createBlock = function (blockId, container, blob, content, stream, length, options, callback) { var resourceName = createResourceName(container, blob); var self = this; var startCreateBlock = function () { var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.COMP, 'block') .withQueryOption(QueryStringConstants.BLOCK_ID, new Buffer(blockId).toString('base64')) .withHeader(HeaderConstants.CONTENT_LENGTH, length); BlobResult.setHeadersFromBlob(webResource, options); var processResponseCallback = function (responseObject, next) { var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.response); }; next(responseObject, finalCallback); }; if (!azureutil.objectIsNull(content)) { self.performRequest(webResource, content, options, processResponseCallback); } else { self.performRequestOutputStream(webResource, stream, options, processResponseCallback); } }; if (azureutil.objectIsNull(options.contentMD5) && options.useTransactionalMD5) { if (!azureutil.objectIsNull(content)) { options.contentMD5 = azureutil.getContentMd5(content); startCreateBlock(); } else { azureutil.calculateMD5(stream, length, options, function (internalBuff) { content = internalBuff; length = internalBuff.length; startCreateBlock(); }); } } else { startCreateBlock(); } }; /** * Writes a blob by specifying the list of block IDs that make up the blob. * In order to be written as part of a blob, a block must have been successfully written to the server in a prior * createBlock operation. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} blockList The block identifiers. * @param {object} [options] The request options. * @param {object} [options.metadata] The metadata key/value pairs. * @param {string} [options.leaseId] The target blob lease identifier. * @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.contentDisposition] The blob's content disposition. (x-ms-blob-content-disposition) * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * the blob result with the blocklist information. * `response` will contain information related to this operation. */ BlobService.prototype.commitBlocks = function (container, blob, blockList, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('commitBlocks', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var blockListXml = BlockListResult.serialize(blockList); var resourceName = createResourceName(container, blob); var options = extend(true, {}, userOptions); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.COMP, 'blocklist') .withHeader(HeaderConstants.CONTENT_LENGTH, Buffer.byteLength(blockListXml)) .withBody(blockListXml); BlobResult.setPropertiesFromBlob(webResource, options); var processResponseCallback = function (responseObject, next) { responseObject.blobResult = new BlobResult(container, blob); responseObject.blobResult.list = null; if (!responseObject.error) { responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers); responseObject.blobResult.list = blockList; } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.blobResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, webResource.body, options, processResponseCallback); }; /** * Retrieves the list of blocks that have been uploaded as part of a block blob. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {BlockListFilter} blocklisttype The type of block list to retrieve. * @param {object} [options] The request options. * @param {string} [options.snapshotId] The source blob snapshot identifier. * @param {string} [options.leaseId] The target blob lease identifier. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * the blocklist information. * `response` will contain information related to this operation. */ BlobService.prototype.listBlocks = function (container, blob, blocklisttype, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('listBlocks', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var resourceName = createResourceName(container, blob); var options = extend(true, {}, userOptions); var webResource = WebResource.get(resourceName) .withQueryOption(QueryStringConstants.COMP, 'blocklist') .withQueryOption(QueryStringConstants.BLOCK_LIST_TYPE, blocklisttype) .withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId); BlobResult.setHeadersFromBlob(webResource, blob); options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY; var processResponseCallback = function (responseObject, next) { responseObject.blockListResult = null; if (!responseObject.error) { responseObject.blockListResult = BlockListResult.parse(responseObject.response.body.BlockList); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.blockListResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Generate a random block id prefix */ BlobService.prototype.generateBlockIdPrefix = function () { var prefix = Math.random().toString(16); return azureutil.zeroPaddingString(prefix, 8); }; /** * Get a block id according to prefix and block number */ BlobService.prototype.getBlockId = function (prefix, number) { return prefix + '-' + azureutil.zeroPaddingString(number, 6); }; // Append blob methods /** * Creates an empty append blob. If the blob already exists on the service, it will be overwritten. * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {object} [options.metadata] The metadata key/value pairs. * @param {string} [options.leaseId] The target blob lease identifier. * @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.contentDisposition] The blob's content disposition. (x-ms-blob-content-disposition) * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback `error` will contain information * if an error occurs; otherwise * `response` will contain information related to this operation. */ BlobService.prototype.createOrReplaceAppendBlob = function (container, blob, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createOrReplaceAppendBlob', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(container, blob); var webResource = WebResource.put(resourceName) .withHeader(HeaderConstants.BLOB_TYPE, BlobConstants.BlobTypes.APPEND) .withHeader(HeaderConstants.LEASE_ID, options.leaseId) .withHeader(HeaderConstants.CONTENT_LENGTH, 0); BlobResult.setHeadersFromBlob(webResource, options); 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 append blob from a local file. If the blob already exists on the service, it will be overwritten. * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object. * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks. * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you. * If you want to append data to an already existing blob, please look at appendFromLocalFile. * * @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 request options. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback The callback function. * @return {SpeedSummary} */ BlobService.prototype.createAppendBlobFromLocalFile = function (container, blob, localFileName, optionsOrCallback, callback) { return this._createBlobFromLocalFile(container, blob, BlobConstants.BlobTypes.APPEND, localFileName, optionsOrCallback, callback); }; /** * Uploads an append blob from a stream. If the blob already exists on the service, it will be overwritten. * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object. * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks. * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you. * If you want to append data to an already existing blob, please look at appendFromStream. * * @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 request options. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. * @param {SpeedSummary} [options.speedSummary] The download tracker objects. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback The callback function. * @return {SpeedSummary} */ BlobService.prototype.createAppendBlobFromStream = function (container, blob, stream, streamLength, optionsOrCallback, callback) { return this._createBlobFromStream(container, blob, BlobConstants.BlobTypes.APPEND, stream, streamLength, optionsOrCallback, callback); }; /** * Uploads an append blob from a text string. If the blob already exists on the service, it will be overwritten. * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object. * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks. * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you. * If you want to append data to an already existing blob, please look at appendFromText. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {string|object} text The blob text, as a string or in a Buffer. * @param {object} [options] The request options. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * information about the blob. * `response` will contain information related to this operation. * @return {undefined} */ BlobService.prototype.createAppendBlobFromText = function (container, blob, text, optionsOrCallback, callback) { return this._createBlobFromText(container, blob, BlobConstants.BlobTypes.APPEND, text, optionsOrCallback, callback); }; /** * Provides a stream to write to a new append blob. If the blob already exists on the service, it will be overwritten. * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object. * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks. * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. * The default value is false for page blobs and true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.position] The blob's content disposition. (x-ms-blob-content-disposition) * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback The callback function. * @return {Stream} * @example * var azure = require('azure-storage'); * var blobService = azure.createBlobService(); * var stream = fs.createReadStream(fileNameTarget).pipe(blobService.createWriteStreamToAppendBlob(containerName, blobName)); */ BlobService.prototype.createWriteStreamToNewAppendBlob = function (container, blob, optionsOrCallback, callback) { return this._createWriteStreamToBlob(container, blob, BlobConstants.BlobTypes.APPEND, 0, true, optionsOrCallback, callback); }; /** * Provides a stream to write to an existing append blob. Assumes that the blob exists. * If it does not, please create the blob using createAppendBlob before calling this method or use createWriteStreamToNewAppendBlob. * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks. * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {object} [options] The request options. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. * The default value is false for page blobs and true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.position] The blob's content disposition. (x-ms-blob-content-disposition) * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback The callback function. * @return {Stream} * @example * var azure = require('azure-storage'); * var blobService = azure.createBlobService(); * var stream = fs.createReadStream(fileNameTarget).pipe(blobService.createWriteStreamToAppendBlob(containerName, blobName)); */ BlobService.prototype.createWriteStreamToExistingAppendBlob = function (container, blob, optionsOrCallback, callback) { return this._createWriteStreamToBlob(container, blob, BlobConstants.BlobTypes.APPEND, 0, false, optionsOrCallback, callback); }; /** * Appends to an append blob from a local file. Assumes the blob already exists on the service. * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks. * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you. * * @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 request options. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback The callback function. * @return {SpeedSummary} */ BlobService.prototype.appendFromLocalFile = function (container, blob, localFileName, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('appendFromLocalFile', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.string(localFileName, 'localFileName'); v.callback(callback); }); var options = extend(true, {}, userOptions); var self = this; fs.stat(localFileName, function (error, stat) { if (error) { callback(error); } else { var stream = new FileReadStream(localFileName, { calcContentMd5: options.storeBlobContentMD5 }); var streamCallback = function (appendError, blob, response) { if (azureutil.objectIsFunction(stream.destroy)) { stream.destroy(); } callback(appendError, blob, response); }; self._uploadBlobFromStream(false, container, blob, BlobConstants.BlobTypes.APPEND, stream, stat.size, options, streamCallback); } }); return options.speedSummary; }; /** * Appends to an append blob from a stream. Assumes the blob already exists on the service. * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks. * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you. * * @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 request options. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. * @param {SpeedSummary} [options.speedSummary] The download tracker objects. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback The callback function. * @return {SpeedSummary} */ BlobService.prototype.appendFromStream = function (container, blob, stream, streamLength, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('_createBlobFromStream', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.exists(stream, 'stream'); v.value(streamLength, 'streamLength'); v.callback(callback); }); return this._uploadBlobFromStream(false, container, blob, BlobConstants.BlobTypes.APPEND, stream, streamLength, options, callback); }; /** * Appends to an append blob from a text string. Assumes the blob already exists on the service. * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks. * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {string|object} text The blob text, as a string or in a Buffer. * @param {object} [options] The request options. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * information about the blob. * `response` will contain information related to this operation. * @return {undefined} */ BlobService.prototype.appendFromText = function (container, blob, text, optionsOrCallback, callback) { return this._uploadBlobFromText(false, container, blob, BlobConstants.BlobTypes.APPEND, text, optionsOrCallback, callback); }; /** * Creates a new block from a read stream to be appended to an append blob. * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks. * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {Stream} readStream The read stream. * @param {int} streamLength The stream length. * @param {object} [options] The request options. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. * @param {int} [options.maxBlobSize] The max length in bytes allowed for the append blob to grow to. * @param {int} [options.appendPosition] The number indicating the byte offset to check for. The append will succeed only if the end position of the blob is equal to this number. * @param {string} [options.leaseId] The target blob lease identifier. * @param {string} [options.contentMD5] The blob’s MD5 hash. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback `error` will contain information * if an error occurs; otherwise * `response` will contain information related to this operation. */ BlobService.prototype.appendBlockFromStream = function (container, blob, readStream, streamLength, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('appendBlockFromStream', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.exists(readStream, 'readStream'); v.value(streamLength, 'streamLength'); v.callback(callback); }); var options = extend(true, {}, userOptions); if (streamLength > BlobConstants.MAX_BLOCK_SIZE) { throw new Error(SR.INVALID_STREAM_LENGTH); } else { this._appendBlock(container, blob, null, readStream, streamLength, options, callback); } }; /** * Creates a new block from a text to be appended to an append blob. * This API should be used strictly in a single writer scenario because the API internally uses the append-offset conditional header to avoid duplicate blocks. * If you are guaranteed to have a single writer scenario, please look at options.absorbConditionalErrorsOnRetry and see if setting this flag to true is acceptable for you. * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {string|object} content The block text, as a string or in a Buffer. * @param {object} [options] The request options. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. * @param {int} [options.maxBlobSize] The max length in bytes allowed for the append blob to grow to. * @param {int} [options.appendPosition] The number indicating the byte offset to check for. The append will succeed only if the end position of the blob is equal to this number. * @param {string} [options.leaseId] The target blob lease identifier. * @param {string} [options.contentMD5] The blob’s MD5 hash. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback `error` will contain information * if an error occurs; otherwise * `response` will contain information related to this operation. */ BlobService.prototype.appendBlockFromText = function (container, blob, content, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('appendBlockFromText', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var contentLength = (Buffer.isBuffer(content) ? content.length : Buffer.byteLength(content)); if (contentLength > BlobConstants.MAX_BLOCK_SIZE) { throw new Error(SR.INVALID_TEXT_LENGTH); } else { this._appendBlock(container, blob, content, null, contentLength, options, callback); } }; // Private methods /** * Creates a new blob (Block/Page/Append). If the blob already exists on the service, it will be overwritten. * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object. * * @ignore * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {BlobType} blobType The blob type. * @param {string} localFileName The local path to the file to be uploaded. * @param {object} [options] The request options. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. (For append blob only) * @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. (For block blob only) * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {int} [options.parallelOperationThreadCount] Parallel operation thread count * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback The callback function. * * @return {SpeedSummary} * */ BlobService.prototype._createBlobFromLocalFile = function (container, blob, blobType, localFileName, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('_createBlobFromLocalFile', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.blobTypeIsValid(blobType); v.string(localFileName, 'localFileName'); v.callback(callback); }); var options = extend(true, {}, userOptions); options.speedSummary = options.speedSummary || new SpeedSummary(blob); var self = this; var size = 0; var creationCallback = function (createError, createBlob, createResponse) { if (createError) { callback(createError, createBlob, createResponse); } else { // Automatically detect the mime type if (options.contentType === undefined) { options.contentType = mime.lookup(localFileName); } var stream = new FileReadStream(localFileName, { calcContentMd5: options.storeBlobContentMD5 }); var streamCallback = function (createError, createBlob, createResponse) { if (azureutil.objectIsFunction(stream.destroy)) { stream.destroy(); } callback(createError, createBlob, createResponse); }; self._uploadBlobFromStream(true, container, blob, blobType, stream, size, options, streamCallback); } }; // Check the file size to determine the upload method: single request or chunks fs.stat(localFileName, function (error, stat) { if (error) { callback(error); } else { size = stat.size; self._createBlob(container, blob, blobType, size, options, creationCallback); } }); return options.speedSummary; }; /** * Creates a new blob from a stream. If the blob already exists on the service, it will be overwritten. * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object. * * @ignore * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {BlobType} blobType The blob type. * @param (Stream) stream Stream to the data to store. * @param {int} streamLength The length of the stream to upload. * @param {object} [options] The request options. * @param {SpeedSummary} [options.speedSummary] The upload tracker objects. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. (For append blob only) * @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. (For block blob only) * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {int} [options.parallelOperationThreadCount] Parallel operation thread count * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback The callback function. * @return {SpeedSummary} */ BlobService.prototype._createBlobFromStream = function (container, blob, blobType, stream, streamLength, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('_createBlobFromStream', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.blobTypeIsValid(blobType); v.exists(stream, 'stream'); v.value(streamLength, 'streamLength'); v.callback(callback); }); var options = extend(true, {}, userOptions); var self = this; var creationCallback = function (createError, createBlob, createResponse) { if (createError) { callback(createError, createBlob, createResponse); } else { self._uploadBlobFromStream(true, container, blob, blobType, stream, streamLength, options, callback); } }; this._createBlob(container, blob, blobType, streamLength, options, creationCallback); return options.speedSummary; }; /** * Uploads a block blob or an append blob from a text string. If the blob already exists on the service, it will be overwritten. * To avoid overwriting and instead throw an error if the blob exists, please pass in an accessConditions parameter in the options object. * * @ignore * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {BlobType} blobType The blob type. * @param {string|buffer} content The blob text, as a string or in a Buffer. * @param {object} [options] The request options. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. (For append blob only) * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * Use options.accessConditions = require('azure-storage').AccessCondition.generateIfNotExistsCondition() * to avoid overwriting and instead throw an error if the blob exists. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * information about the blob. * `response` will contain information related to this operation. * @return {undefined} */ BlobService.prototype._createBlobFromText = function (container, blob, blobType, content, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('_createBlobFromText', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.blobTypeIsValid(blobType); v.callback(callback); }); var options = extend(true, {}, userOptions); var self = this; var creationCallback = function (createError, createBlob, createResponse) { if (createError) { callback(createError, createBlob, createResponse); } else { self._uploadBlobFromText(true, container, blob, blobType, content, options, callback); } }; var contentLength = (Buffer.isBuffer(content) ? content.length : Buffer.byteLength(content)); this._createBlob(container, blob, blobType, contentLength, options, creationCallback); return options.speedSummary; }; /** * Provides a stream to write to a block blob or an append blob. * * @ignore * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {BlobType} blobType The blob type. * @param {int} length The blob length. * @param {bool} createNewBlob Specifies whether create a new blob. * @param {object} [options] The request options. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. (For append blob only) * @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. (For block blob only) * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {int} [options.parallelOperationThreadCount] Parallel operation thread count * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. * The default value is false for page blobs and true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.position] The blob's content disposition. (x-ms-blob-content-disposition) * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback The callback function. * @return {Stream} */ BlobService.prototype._createWriteStreamToBlob = function (container, blob, blobType, length, createNewBlob, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('_createWriteStreamToBlob', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.blobTypeIsValid(blobType); }); var options = extend(true, {}, userOptions); if (blobType === BlobConstants.BlobTypes.BLOCK) { // default to true, unless explicitly set to false options.storeBlobContentMD5 = options.storeBlobContentMD5 === false ? false : true; } var stream = new ChunkStream({ calcContentMd5: options.storeBlobContentMD5 }); stream.pause(); //Immediately pause the stream in order to wait for the destination to getting ready var self = this; var createCallback = function (createError, createBlob, createResponse) { if (createError) { if (callback) { callback(createError, createBlob, createResponse); } } else { self._uploadBlobFromStream(createNewBlob, container, blob, blobType, stream, null, options, function (error, blob, response) { if (error) { stream.emit('error', error); } if (callback) { callback(error, blob, response); } }); } }; if (createNewBlob === true) { this._createBlob(container, blob, blobType, length, options, createCallback); } else { createCallback(); } return stream; }; /** * Upload blob content from a stream. Assumes the blob already exists. * * @ignore * * @this {BlobService} * @param {bool} isNewBlob Specifies whether the blob is newly created. * @param {string} container The container name. * @param {string} blob The blob name. * @param {BlobType} blobType The blob type. * @param (Stream) stream Stream to the data to store. * @param {int} streamLength The length of the stream to upload. * @param {object} [options] The request options. * @param {SpeedSummary} [options.speedSummary] The upload tracker objects. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. (For append blob only) * @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. (For block blob only) * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {int} [options.parallelOperationThreadCount] Parallel operation thread count * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback The callback function. * @return {SpeedSummary} */ BlobService.prototype._uploadBlobFromStream = function (isNewBlob, container, blob, blobType, stream, streamLength, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); options.speedSummary = options.speedSummary || new SpeedSummary(blob); if (blobType === BlobConstants.BlobTypes.BLOCK) { // default to true, unless explicitly set to false options.storeBlobContentMD5 = options.storeBlobContentMD5 === false ? false : true; } stream.pause(); var self = this; var startUpload = function () { var putBlockBlobFromStream = function () { var finalCallback = function (error, result, response) { if (error) { callback(error, result, response); } else { callback(error, blob, response); } }; if (streamLength > 0 && azureutil.objectIsNull(options.contentMD5) && options.storeBlobContentMD5) { azureutil.calculateMD5(stream, Math.min(self.singleBlobPutThresholdInBytes, streamLength), options, function (internalBuff) { self._putBlockBlob(container, blob, internalBuff, null, internalBuff.length, options, finalCallback); }); stream.resume(); } else { // Stream will resume when it has a pipe destination or a 'data' listener self._putBlockBlob(container, blob, null, stream, streamLength, options, finalCallback); } }; if (streamLength === null || streamLength >= self.singleBlobPutThresholdInBytes || blobType !== BlobConstants.BlobTypes.BLOCK) { var chunkStream = new ChunkStreamWithStream(stream, { calcContentMd5: options.storeBlobContentMD5 }); self._uploadContentFromChunkStream(container, blob, blobType, chunkStream, streamLength, options, callback); } else { putBlockBlobFromStream(); } }; if (!isNewBlob) { if (options.storeBlobContentMD5 && blobType !== BlobConstants.BlobTypes.BLOCK ) { throw new Error(SR.MD5_NOT_POSSIBLE); } if (blobType === BlobConstants.BlobTypes.APPEND || (options.accessConditions && options.accessConditions.length > 0)) { // Do a getBlobProperties right at the beginning for existing blobs and use the user passed in access conditions. // So any pre-condition failure on the first block (in a strictly single writer scenario) is caught. // This call also helps us get the append position to append to if the user hasn’t specified an access condition. this.getBlobProperties(container, blob, options, function (error, properties) { if (error) { callback(error); } else { if (blobType === BlobConstants.BlobTypes.APPEND) { options.appendPosition = properties.contentLength; } startUpload(); } }); } else { startUpload(); } } else { startUpload(); } return options.speedSummary; }; /** * Upload blob content from a text. Assumes the blob already exists. * * @ignore * * @this {BlobService} * @param {bool} isNewBlob Specifies whether the blob is newly created. * @param {string} container The container name. * @param {string} blob The blob name. * @param {BlobType} blobType The blob type. * @param (string) content The blob text, as a string or in a Buffer. * @param {object} [options] The request options. * @param {SpeedSummary} [options.speedSummary] The upload tracker objects. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. (For append blob only) * @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. (For block blob only) * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {int} [options.parallelOperationThreadCount] Parallel operation thread count * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback The callback function. * @return {SpeedSummary} */ BlobService.prototype._uploadBlobFromText = function (isNewBlob, container, blob, blobType, content, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); options.speedSummary = options.speedSummary || new SpeedSummary(blob); options[HeaderConstants.CONTENT_TYPE] = 'text/plain;charset="utf-8"'; var self = this; var startUpload = function () { var operationFunc; var length = Buffer.isBuffer(content) ? content.length : Buffer.byteLength(content); if (blobType === BlobConstants.BlobTypes.BLOCK) { // default to true, unless explicitly set to false options.storeBlobContentMD5 = options.storeBlobContentMD5 === false ? false : true; operationFunc = self._putBlockBlob; if (length > BlobConstants.MAX_SINGLE_UPLOAD_BLOB_SIZE_IN_BYTES) { throw new Error(SR.INVALID_BLOB_LENGTH); } } else if (blobType === BlobConstants.BlobTypes.APPEND) { operationFunc = self._appendBlock; if (length > BlobConstants.MAX_BLOCK_SIZE) { throw new Error(SR.INVALID_TEXT_LENGTH); } } var finalCallback = function (error, blobResult, response) { if (blobType !== BlobConstants.BlobTypes.BLOCK) { self.setBlobProperties(container, blob, options, function (error, blob, response) { blob = extend(false, blob, blobResult); callback(error, blob, response); }); } else { callback(error, blobResult, response); } }; operationFunc.call(self, container, blob, content, null, length, options, finalCallback); }; if (!isNewBlob) { if (options.storeBlobContentMD5 && blobType !== BlobConstants.BlobTypes.BLOCK ) { throw new Error(SR.MD5_NOT_POSSIBLE); } if (blobType === BlobConstants.BlobTypes.APPEND || (options.accessConditions && options.accessConditions.length > 0)) { // Do a getBlobProperties right at the beginning for existing blobs and use the user passed in access conditions. // So any pre-condition failure on the first block (in a strictly single writer scenario) is caught. // This call also helps us get the append position to append to if the user hasn’t specified an access condition. this.getBlobProperties(container, blob, options, function (error, properties) { if (error) { callback(error); } else { if (blobType === BlobConstants.BlobTypes.APPEND) { options.appendPosition = properties.contentLength; } startUpload(); } }); } } else { if (!azureutil.objectIsNull(content) && azureutil.objectIsNull(options.contentMD5) && options.storeBlobContentMD5) { options.contentMD5 = azureutil.getContentMd5(content); } startUpload(); } }; /** * Uploads a block blob from a stream. * @ignore * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {string} text The blob text. * @param (Stream) stream Stream to the data to store. * @param {int} length The length of the stream or text to upload. * @param {object} [options] The request options. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. The default value is true for block blobs. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * information about the blob. * `response` will contain information related to this operation. * @return {undefined} * */ BlobService.prototype._putBlockBlob = function (container, blob, text, stream, length, options, callback) { if (!options.speedSummary) { options.speedSummary = new SpeedSummary(blob); } var speedSummary = options.speedSummary; speedSummary.totalSize = length; var resourceName = createResourceName(container, blob); var webResource = WebResource.put(resourceName) .withHeader(HeaderConstants.CONTENT_TYPE, 'application/octet-stream') .withHeader(HeaderConstants.BLOB_TYPE, BlobConstants.BlobTypes.BLOCK) .withHeader(HeaderConstants.CONTENT_LENGTH, length); if (!azureutil.objectIsNull(text) && azureutil.objectIsNull(options.contentMD5) && options.useTransactionalMD5) { options.contentMD5 = azureutil.getContentMd5(text); } BlobResult.setHeadersFromBlob(webResource, options); var processResponseCallback = function (responseObject, next) { responseObject.blobResult = null; if (!responseObject.error) { responseObject.blobResult = new BlobResult(container, blob); responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers); if (options.metadata) { responseObject.blobResult.metadata = options.metadata; } } var finalCallback = function (returnObject) { if (!returnObject || !returnObject.error) { speedSummary.increment(length); } callback(returnObject.error, returnObject.blobResult, returnObject.response); }; next(responseObject, finalCallback); }; if (!azureutil.objectIsNull(text)) { this.performRequest(webResource, text, options, processResponseCallback); } else { this.performRequestOutputStream(webResource, stream, options, processResponseCallback); } return options.speedSummary; }; /** * Appends a new block to an append blob. * * @ignore * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {string|buffer} content The block content. * @param (Stream) stream The stream to the data to store. * @param {int} length The length of the stream or content to upload. * @param {object} [options] The request options. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. * @param {int} [options.maxBlobSize] The max length in bytes allowed for the append blob to grow to. * @param {int} [options.appendPosition] The number indicating the byte offset to check for. The append will succeed only if the end position of the blob is equal to this number. * @param {string} [options.leaseId] The target blob lease identifier. * @param {string} [options.contentMD5] The blob’s MD5 hash. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback `error` will contain information * if an error occurs; otherwise * `response` will contain information related to this operation. */ BlobService.prototype._appendBlock = function (container, blob, content, stream, length, options, callback) { var speedSummary = options.speedSummary || new SpeedSummary(blob); speedSummary.totalSize = length; var self = this; var startAppendBlock = function () { var resourceName = createResourceName(container, blob); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.COMP, 'appendblock') .withHeader(HeaderConstants.CONTENT_LENGTH, length) .withHeader(HeaderConstants.BLOB_CONDITION_MAX_SIZE, options.maxBlobSize) .withHeader(HeaderConstants.BLOB_CONDITION_APPEND_POSITION, options.appendPosition || 0); BlobResult.setHeadersFromBlob(webResource, options); var processResponseCallback = function (responseObject, next) { responseObject.blobResult = null; if (!responseObject.error) { responseObject.blobResult = new BlobResult(container, blob); responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { if (!returnObject || !returnObject.error) { speedSummary.increment(length); } callback(returnObject.error, returnObject.blobResult, returnObject.response); }; next(responseObject, finalCallback); }; if (!azureutil.objectIsNull(content)) { self.performRequest(webResource, content, options, processResponseCallback); } else { self.performRequestOutputStream(webResource, stream, options, processResponseCallback); } }; if (azureutil.objectIsNull(options.contentMD5) && options.useTransactionalMD5) { if (!azureutil.objectIsNull(content)) { options.contentMD5 = azureutil.getContentMd5(content); startAppendBlock(); } else { azureutil.calculateMD5(stream, length, options, function (internalBuff) { content = internalBuff; length = internalBuff.length; startAppendBlock(); }); } } else { startAppendBlock(); } return options.speedSummary; }; /** * Creates and dispatches lease requests. * @ignore * * @this {BlobService} * @param {object} webResource The web resource. * @param {string} container The container name. * @param {string} blob The blob name. * @param {string} leaseId The lease identifier. Required to renew, change or release the lease. * @param {string} leaseAction The lease action (BlobConstants.LeaseOperation.*). Required. * @param {object} userOptions The request options. * @param {int} [userOptions.leaseBreakPeriod] The lease break period. * @param {string} [userOptions.leaseDuration] The lease duration. Default is never to expire. * @param {string} [userOptions.proposedLeaseId] The proposed lease identifier. This is required for the CHANGE lease action. * @param {LocationMode} [userOptions.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {object} [userOptions.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {int} [userOptions.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [userOptions.maximumExecutionTimeInMs]The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {Function(error, lease, response)} callback `error` will contain information * if an error occurs; otherwise `lease` will contain * the lease information. * `response` will contain information related to this operation. */ BlobService.prototype._leaseImpl = function (container, blob, leaseId, leaseAction, options, callback) { var webResource; if (!azureutil.objectIsNull(blob)) { validate.validateArgs('_leaseImpl', function (v) { v.string(blob, 'blob'); }); var resourceName = createResourceName(container, blob); webResource = WebResource.put(resourceName); } else { webResource = WebResource.put(container) .withQueryOption(QueryStringConstants.RESTYPE, 'container'); } webResource.withQueryOption(QueryStringConstants.COMP, 'lease') .withHeader(HeaderConstants.LEASE_ID, leaseId) .withHeader(HeaderConstants.LEASE_ACTION, leaseAction.toLowerCase()) .withHeader(HeaderConstants.LEASE_BREAK_PERIOD, options.leaseBreakPeriod) .withHeader(HeaderConstants.PROPOSED_LEASE_ID, options.proposedLeaseId) .withHeader(HeaderConstants.LEASE_DURATION, options.leaseDuration); var processResponseCallback = function (responseObject, next) { responseObject.leaseResult = null; if (!responseObject.error) { responseObject.leaseResult = new LeaseResult(container, blob); responseObject.leaseResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.leaseResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Updates a page blob from text. * @ignore * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {string} text The text string. * @param {Stream} readStream The read stream. * @param {int} rangeStart The range start. * @param {int} rangeEnd The range end. * @param {object} [options] The request options. * @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 {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {Function(error, pageBlob, response)} callback `error` will contain information * if an error occurs; otherwise `pageBlob` will contain * the blob information. * `response` will contain information related to this operation. */ BlobService.prototype._createPages = function (container, blob, text, readStream, rangeStart, rangeEnd, options, callback) { var request = this._updatePageBlobPagesImpl(container, blob, rangeStart, rangeEnd, BlobConstants.PageWriteOptions.UPDATE, options); // At this point, we have already validated that the range is less than 4MB. Therefore, we just need to calculate the contentMD5 if required. // Even when this is called from the createPagesFromStream method, it is pre-buffered and called with text. if (!azureutil.objectIsNull(text) && azureutil.objectIsNull(options.contentMD5) && options.useTransactionalMD5) { request.withHeader(HeaderConstants.CONTENT_MD5, azureutil.getContentMd5(text)); } var processResponseCallback = function (responseObject, next) { responseObject.blobResult = null; if (!responseObject.error) { responseObject.blobResult = new BlobResult(container, blob); responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.blobResult, returnObject.response); }; next(responseObject, finalCallback); }; if (!azureutil.objectIsNull(text)) { this.performRequest(request, text, options, processResponseCallback); } else { this.performRequestOutputStream(request, readStream, options, processResponseCallback); } }; /** * @ignore */ BlobService.prototype._updatePageBlobPagesImpl = function (container, blob, rangeStart, rangeEnd, writeMethod, options) { if (rangeStart && rangeStart % BlobConstants.PAGE_SIZE !== 0) { throw new Error(SR.INVALID_PAGE_START_OFFSET); } if (rangeEnd && (rangeEnd + 1) % BlobConstants.PAGE_SIZE !== 0) { throw new Error(SR.INVALID_PAGE_END_OFFSET); } // this is necessary if this is called from _uploadContentFromChunkStream->_createPages if (!options) { options = {}; } options.rangeStart = rangeStart; options.rangeEnd = rangeEnd; options.contentLength = writeMethod === BlobConstants.PageWriteOptions.UPDATE ? (rangeEnd - rangeStart) + 1 : 0; var resourceName = createResourceName(container, blob); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.COMP, 'page') .withHeader(HeaderConstants.CONTENT_TYPE, 'application/octet-stream') .withHeader(HeaderConstants.PAGE_WRITE, writeMethod); BlobResult.setHeadersFromBlob(webResource, options); return webResource; }; /** * Uploads blob content from a stream. * For block blob, it creates a new block to be committed. * For page blob, it writes a range of pages. * For append blob, it appends a new block. * * @ignore * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {string} blobType The blob type. * @param (Stream) stream Stream to the data to store. * @param {int} streamLength The length of the stream to upload. * @param {object|function} [options] The request options. * @param {SpeedSummary} [options.speedSummary] The download tracker objects; * @param {int} [options.parallelOperationThreadCount] Parallel operation thread count. * @param {bool} [options.absorbConditionalErrorsOnRetry] Specifies whether to absorb the conditional error on retry. (For append blob only) * @param {int} [options.maxBlobSize] The max length in bytes allowed for the append blob to grow to. * @param {int} [options.appendPosition] The number indicating the byte offset to check for. The append will succeed only if the end position of the blob is equal to this number. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @param {string} [options.blockIdPrefix] The prefix to be used to generate the block id. * @param {string} [options.leaseId] The lease identifier. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeBlobContentMD5] Specifies whether the blob's ContentMD5 header should be set on uploads. * @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.contentDisposition] The blob's content disposition. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {function(error, null)} callback The callback function. * @return {SpeedSummary} */ BlobService.prototype._uploadContentFromChunkStream = function (container, blob, blobType, chunkStream, streamLength, options, callback) { this.logger.debug(util.format('_uploadContentFromChunkStream for blob %s', blob)); var apiName; var isBlockBlobUpload; var isPageBlobUpload; var isAppendBlobUpload; var sizeLimitation; var originalContentMD5 = options.contentMD5; var parallelOperationThreadCount = options.parallelOperationThreadCount || this.parallelOperationThreadCount; if (blobType == BlobConstants.BlobTypes.BLOCK) { apiName = 'createBlockFromText'; isBlockBlobUpload = true; sizeLimitation = BlobConstants.DEFAULT_WRITE_BLOCK_SIZE_IN_BYTES; } else if (blobType == BlobConstants.BlobTypes.PAGE) { apiName = '_createPages'; isPageBlobUpload = true; sizeLimitation = BlobConstants.DEFAULT_WRITE_PAGE_SIZE_IN_BYTES; } else if (blobType == BlobConstants.BlobTypes.APPEND) { apiName = 'appendBlockFromText'; isAppendBlobUpload = true; parallelOperationThreadCount = 1; sizeLimitation = BlobConstants.DEFAULT_WRITE_BLOCK_SIZE_IN_BYTES; } else { var error = new Error(util.format('Unknown blob type %s', blobType)); callback(error); return; } this._setOperationExpiryTime(options); // initialize the speed summary var speedSummary = options.speedSummary || new SpeedSummary(blob); speedSummary.totalSize = streamLength; // initialize chunk allocator var allocator = new ChunkAllocator(sizeLimitation, options.parallelOperationThreadCount, { logger: this.logger }); chunkStream.setOutputLength(streamLength); // if this is a FileReadStream, set the allocator on that stream if (chunkStream._stream && chunkStream._stream.setMemoryAllocator) { chunkStream._stream.setMemoryAllocator(allocator); } // initialize batch operations var batchOperations = new BatchOperation(apiName, { callInOrder: isAppendBlobUpload, callbackInOrder: isAppendBlobUpload, logger : this.logger }); batchOperations.setConcurrency(parallelOperationThreadCount); // initialize options var rangeOptions = { leaseId: options.leaseId, timeoutIntervalInMs: options.timeoutIntervalInMs, operationExpiryTime: options.operationExpiryTime, maxBlobSize: options.maxBlobSize, appendPosition: options.appendPosition || 0, initialAppendPosition: options.appendPosition || 0, absorbConditionalErrorsOnRetry: options.absorbConditionalErrorsOnRetry }; // initialize block blob variables var blockIdPrefix = options.blockIdPrefix || this.generateBlockIdPrefix(); var blockCount = 0; var blockIds = []; var blobResult = {}; var self = this; chunkStream.on('data', function (data, range) { var operation = null; var full = false; var autoIncrement = speedSummary.getAutoIncrementFunction(data.length); if (data.length > sizeLimitation) { throw new Error(util.format(SR.EXCEEDED_SIZE_LIMITATION, sizeLimitation, data.length)); } if (options.useTransactionalMD5) { //calculate content md5 for the current uploading block data var contentMD5 = azureutil.getContentMd5(data); rangeOptions.contentMD5 = contentMD5; } var checkLengthLimit = function () { if (!streamLength) return true; if (range.start >= streamLength) { self.logger.debug(util.format('Stop uploading data from %s bytes to %s bytes to blob %s because of limit %s', range.start, range.end, blob, streamLength)); chunkStream.stop(); return false; } else if (range.end >= streamLength) { self.logger.debug(util.format('Clip uploading data from %s bytes to %s bytes to blob %s because of limit %s', range.start, range.end, blob, streamLength)); range.end = streamLength - 1; data = data.slice(0, streamLength - range.start); if (options.useTransactionalMD5) { rangeOptions.contentMD5 = azureutil.getContentMd5(data); } } return true; }; var uploadBlockBlobChunk = function () { if (!checkLengthLimit()) return; var blockId = self.getBlockId(blockIdPrefix, blockCount); blockIds.push(blockId); operation = new BatchOperation.RestOperation(self, apiName, blockId, container, blob, data, rangeOptions, function (error) { if (!error) { autoIncrement(); } allocator.releaseBuffer(data); data = null; }); blockCount++; }; var uploadPageBlobChunk = function () { if (!checkLengthLimit()) return; if (azureutil.isBufferAllZero(data)) { self.logger.debug(util.format('Skip upload data from %s bytes to %s bytes to blob %s', range.start, range.end, blob)); speedSummary.increment(data.length); } else { self.logger.debug(util.format('Upload data from %s bytes to %s bytes to blob %s', range.start, range.end, blob)); operation = new BatchOperation.RestOperation(self, apiName, container, blob, data, null, range.start, range.end, rangeOptions, function (error) { if (!error) { autoIncrement(); } else { self.logger.debug(util.format('Error: %s', require('util').inspect(error))); } allocator.releaseBuffer(data); data = null; }); } }; var uploadAppendBlobChunk = function () { if (!checkLengthLimit()) return; rangeOptions.appendPosition = Number(rangeOptions.initialAppendPosition) + Number(range.start); // We cannot differentiate between max size condition failing only in the retry versus failing in the first attempt and retry. // So we will eliminate the latter and handle the former in the append operation callback. if (options.maxBlobSize && rangeOptions.appendPosition + data.length > options.maxBlobSize) { throw new Error(SR.MAX_BLOB_SIZE_CONDITION_NOT_MEET); } operation = new BatchOperation.RestOperation(self, apiName, container, blob, data, rangeOptions, function (error, currentBlob) { if (!error) { autoIncrement(); } blobResult = currentBlob; allocator.releaseBuffer(data); data = null; }); }; if (isBlockBlobUpload) { uploadBlockBlobChunk(); } else if (isAppendBlobUpload) { uploadAppendBlobChunk(); } else if (isPageBlobUpload) { uploadPageBlobChunk(); } if (operation) { full = batchOperations.addOperation(operation); operation = null; if (full) { self.logger.debug('File stream paused'); chunkStream.pause(); } } }); chunkStream.on('end', function () { self.logger.debug(util.format('File read stream ended for blob %s', blob)); batchOperations.enableComplete(); }); batchOperations.on('drain', function () { self.logger.debug('file stream resume'); chunkStream.resume(); }); batchOperations.on('end', function (error) { self.logger.debug('batch operations commited'); speedSummary = null; if (error) { callback(error); return; } if (originalContentMD5) { options.contentMD5 = originalContentMD5; } else if (options.storeBlobContentMD5) { options.contentMD5 = chunkStream.getContentMd5('base64'); } if (isBlockBlobUpload) { //commit block list var blockList = { 'UncommittedBlocks': blockIds }; self.commitBlocks(container, blob, blockList, options, function (error, blockList, response) { self.logger.debug(util.format('Blob %s committed', blob)); if (error) { chunkStream.finish(); callback(error); } else { blobResult['commmittedBlocks'] = blockIds; chunkStream.finish(); callback(error, blobResult, response); } }); } else { // upload page blob or append blob completely self.setBlobProperties(container, blob, options, function (error, blob, response) { chunkStream.finish(); blob = extend(false, blob, blobResult); callback(error, blob, response); }); } }); return speedSummary; }; /** * Checks whether or not a container exists on the service. * @ignore * * @this {BlobService} * @param {string} container The container name. * @param {string} primaryOnly If true, the request will be executed against the primary storage location. * @param {object} [options] The request options. * @param {string} [options.leaseId] The lease identifier. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {Function(error, containerExists, response)} callback `error` will contain information * if an error occurs; otherwise `containerExists` will contain * be true if the container exists, or false if the container does not exist. * `response` will contain information related to this operation. */ BlobService.prototype._doesContainerExist = function (container, primaryOnly, options, callback) { var webResource = WebResource.head(container) .withQueryOption(QueryStringConstants.RESTYPE, 'container') .withHeader(HeaderConstants.LEASE_ID, options.leaseId); if (primaryOnly === false) { options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY; } var processResponseCallback = function (responseObject, next) { if (!responseObject.error) { responseObject.exists = true; } else if (responseObject.error && responseObject.error.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound) { responseObject.error = null; responseObject.exists = false; responseObject.response.isSuccessful = true; } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.exists, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Checks whether or not a blob exists on the service. * @ignore * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {string} primaryOnly If true, the request will be executed against the primary storage location. * @param {object} [options] The request options. * @param {string} [options.leaseId] The lease identifier. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {Function(error, blobExists, response)} callback `error` will contain information * if an error occurs; otherwise `blobExists` will * be true if the blob exists, or false if the blob does not exist. * `response` will contain information related to this operation. */ BlobService.prototype._doesBlobExist = function (container, blob, primaryOnly, options, callback) { var resourceName = createResourceName(container, blob); var webResource = WebResource.head(resourceName) .withHeader(HeaderConstants.LEASE_ID, options.leaseId); if (primaryOnly === false) { options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY; } var processResponseCallback = function (responseObject, next) { if (!responseObject.error) { responseObject.exists = true; } else if (responseObject.error && responseObject.error.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound) { responseObject.error = null; responseObject.exists = false; responseObject.response.isSuccessful = true; } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.exists, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * @ignore */ BlobService.prototype._setBlobPropertiesHelper = function (settings) { var processResponseCallback = function (responseObject, next) { responseObject.blobResult = null; if (!responseObject.error) { responseObject.blobResult = new BlobResult(settings.container, settings.blob); responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { settings.callback(returnObject.error, returnObject.blobResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(settings.webResource, null, settings.options, processResponseCallback); }; /** * @ignore */ BlobService.prototype._validateLengthAndMD5 = function (options, responseObject) { var storedMD5 = responseObject.response.headers[Constants.HeaderConstants.CONTENT_MD5]; var contentLength; if (!azureutil.objectIsNull(responseObject.response.headers[Constants.HeaderConstants.CONTENT_LENGTH])) { contentLength = parseInt(responseObject.response.headers[Constants.HeaderConstants.CONTENT_LENGTH], 10); } // If the user has not specified this option, the default value should be false. if (azureutil.objectIsNull(options.disableContentMD5Validation)) { options.disableContentMD5Validation = false; } // None of the below cases should be retried. So set the error in every case so the retry policy filter handle knows that it shouldn't be retried. if (options.disableContentMD5Validation === false && options.useTransactionalMD5 === true && azureutil.objectIsNull(storedMD5)) { responseObject.error = new Error(SR.MD5_NOT_PRESENT_ERROR); responseObject.retryable = false; } // Validate length and if required, MD5. // If getBlobToText called this method, then the responseObject.length and responseObject.contentMD5 are not set. Calculate them first using responseObject.response.body and then validate. if (azureutil.objectIsNull(responseObject.length)) { if (typeof responseObject.response.body == 'string') { responseObject.length = Buffer.byteLength(responseObject.response.body); } else if (Buffer.isBuffer(responseObject.response.body)) { responseObject.length = responseObject.response.body.length; } } if (!azureutil.objectIsNull(contentLength) && responseObject.length !== contentLength) { responseObject.error = new Error(SR.CONTENT_LENGTH_MISMATCH); responseObject.retryable = false; } if (options.disableContentMD5Validation === false && azureutil.objectIsNull(responseObject.contentMD5)) { responseObject.contentMD5 = azureutil.getContentMd5(responseObject.response.body); } if (options.disableContentMD5Validation === false && !azureutil.objectIsNull(storedMD5) && storedMD5 !== responseObject.contentMD5) { responseObject.error = new Error(util.format(SR.HASH_MISMATCH, storedMD5, responseObject.contentMD5)); responseObject.retryable = false; } }; /** * @ignore */ BlobService.prototype._setRangeContentMD5Header = function (webResource, options) { if (!azureutil.objectIsNull(options.rangeStart) && options.useTransactionalMD5) { if (azureutil.objectIsNull(options.rangeEnd)) { throw new Error(util.format(SR.ARGUMENT_NULL_OR_EMPTY, options.rangeEndHeader)); } var size = parseInt(options.rangeEnd, 10) - parseInt(options.rangeStart, 10) + 1; if (size > BlobConstants.MAX_RANGE_GET_SIZE_WITH_MD5) { throw new Error(SR.INVALID_RANGE_FOR_MD5); } else { webResource.withHeader(HeaderConstants.RANGE_GET_CONTENT_MD5, 'true'); } } }; /** * Downloads a blockblob, pageblob or appendblob into a range stream. * @ignore * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {string} blobType The type of blob to download: block blob, page blob or append blob. * @param {Stream} writeStream The write stream. * @param {object} [options] The request options. * @param {SpeedSummary} [options.speedSummary] The download tracker objects. * @param {int} [options.parallelOperationThreadCount] Parallel operation thread count * @param {string} [options.snapshotId] The snapshot identifier. * @param {string} [options.leaseId] The lease identifier. * @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range. * @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions. * @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the blob information. * `response` will contain information related to this operation. * @return {SpeedSummary} */ BlobService.prototype._getBlobToRangeStream = function (container, blob, blobType, writeStream, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); validate.validateArgs('_getBlobToRangeStream', function (v) { v.string(container, 'container'); v.string(blob, 'blob'); v.containerNameIsValid(container); v.blobNameIsValid(container, blob); v.blobTypeIsValid(blobType); v.callback(callback); }); var rangeStream = null; var isPageBlobDownload = true; if (blobType == BlobConstants.BlobTypes.PAGE) { rangeStream = new PageRangeStream(this, container, blob, options); } else if (blobType == BlobConstants.BlobTypes.APPEND) { rangeStream = new RangeStream(this, container, blob, options); isPageBlobDownload = false; } else if (blobType == BlobConstants.BlobTypes.BLOCK) { rangeStream = new BlockRangeStream(this, container, blob, options); isPageBlobDownload = false; } if (!options.speedSummary) { options.speedSummary = new SpeedSummary(blob); } var speedSummary = options.speedSummary; var parallelOperationThreadCount = options.parallelOperationThreadCount || this.parallelOperationThreadCount; var batchOperations = new BatchOperation('getBlobInRanges', { callbackInOrder: true, logger : this.logger }); batchOperations.setConcurrency(parallelOperationThreadCount); var self = this; var checkMD5sum = !options.disableContentMD5Validation; var md5Hash = null; if (checkMD5sum) { md5Hash = crypto.createHash('md5'); } var savedBlobResult = null; var savedBlobResponse = null; rangeStream.on('range', function (range) { if (!speedSummary.totalSize) { speedSummary.totalSize = rangeStream.rangeSize; } var requestOptions = { rangeStart : range.start, rangeEnd : range.end, responseEncoding : null //Use Buffer to store the response data }; var rangeSize = range.size; requestOptions.timeoutIntervalInMs = options.timeoutIntervalInMs; if (range.dataSize === 0) { if (isPageBlobDownload) { var autoIncrement = speedSummary.getAutoIncrementFunction(rangeSize); //No operation to do and only wait for write zero to file in callback var writeZeroOperation = new BatchOperation.CommonOperation(BatchOperation.noOperation, function (error) { if (error) return; var bufferAvailable = azureutil.writeZerosToStream(writeStream, rangeSize, md5Hash, autoIncrement); //There is no need to pause the rangestream since we can perform http request and write disk at the same time self.logger.debug(util.format('Write %s bytes Zero from %s to %s', rangeSize, range.start, range.end)); if (!bufferAvailable) { self.logger.debug('Write stream is full and pause batch operation'); batchOperations.pause(); } }); batchOperations.addOperation(writeZeroOperation); } else { self.logger.debug(util.format('Can not read %s bytes to %s bytes of blob %s', range.start, range.end, blob)); } return; } if (range.start > range.end) { return; } var operation = new BatchOperation.RestOperation(self, 'getBlobToText', container, blob, requestOptions, function (error, content, blobResult, response) { if (!error) { if (rangeSize !== content.length) { self.logger.warn(util.format('Request %s bytes, but server returns %s bytes', rangeSize, content.length)); } //Save one of the succeeded callback parameters and use them at the final callback if (!savedBlobResult) { savedBlobResult = blobResult; } if (!savedBlobResponse) { savedBlobResponse = response; } var autoIncrement = speedSummary.getAutoIncrementFunction(content.length); var bufferAvailable = writeStream.write(content, autoIncrement); if (!bufferAvailable) { self.logger.debug('Write stream is full and pause batch operation'); batchOperations.pause(); } if (md5Hash) { md5Hash.update(content); } content = null; } }); var full = batchOperations.addOperation(operation); if (full) { self.logger.debug('Pause range stream'); rangeStream.pause(); } }); rangeStream.on('end', function () { self.logger.debug('Range stream has ended.'); batchOperations.enableComplete(); }); batchOperations.on('drain', function () { self.logger.debug('Resume range stream'); rangeStream.resume(); }); writeStream.on('drain', function () { self.logger.debug('Resume batch operations'); batchOperations.resume(); }); batchOperations.on('end', function (error) { self.logger.debug('Download completed!'); if (error) { callback(error); return; } else { writeStream.end(function () { self.logger.debug('Write stream has ended'); if (writeStream.close) { writeStream.close(); } if (!savedBlobResult) { savedBlobResult = {}; } savedBlobResult.contentMD5 = options.contentMD5; savedBlobResult.clientSideContentMD5 = null; if (md5Hash) { savedBlobResult.clientSideContentMD5 = md5Hash.digest('base64'); } callback(error, savedBlobResult, savedBlobResponse); }); } }); var listOptions = { timeoutIntervalInMs : options.timeoutIntervalInMs, snapshotId : options.snapshotId, leaseId : options.leaseId }; rangeStream.list(listOptions, function (error) { callback(error); }); return speedSummary; }; /** * Downloads a blockblob or pageblob into a stream. * @ignore * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param {Stream} writeStream The write stream. * @param {object} [options] The request options. * @param {string} [options.snapshotId] The snapshot identifier. * @param {string} [options.leaseId] The lease identifier. * @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range. * @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions. * @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the blob information. * `response` will contain information related to this operation. */ BlobService.prototype._getBlobToStream = function (container, blob, writeStream, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); var resourceName = createResourceName(container, blob); var webResource = WebResource.get(resourceName).withRawResponse(); var options = extend(true, {}, userOptions); webResource.withQueryOption(QueryStringConstants.SNAPSHOT, options.snapshotId); BlobResult.setHeadersFromBlob(webResource, options); this._setRangeContentMD5Header(webResource, options); var self = this; var processResponseCallback = function (responseObject, next) { responseObject.blobResult = null; if (!responseObject.error) { responseObject.blobResult = new BlobResult(container, blob); responseObject.blobResult.metadata = self.parseMetadataHeaders(responseObject.response.headers); responseObject.blobResult.getPropertiesFromHeaders(responseObject.response.headers); self._validateLengthAndMD5(options, responseObject); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.blobResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequestInputStream(webResource, null, writeStream, options, processResponseCallback); }; /** * Downloads a blob into a file. * @ignore * @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 downloaded. * @param {object} [options] The request options. * @param {boolean} [options.skipSizeCheck] Skip the size check to perform direct download. * Set the option to true for small blobs. * Parallel download and speed summary won't work with this option on. * @param {SpeedSummary} [options.speedSummary] The download tracker objects. * @param {string} [options.snapshotId] The snapshot identifier. * @param {string} [options.leaseId] The lease identifier. * @param {string} [options.rangeStart] Return only the bytes of the blob in the specified range. * @param {string} [options.rangeEnd] Return only the bytes of the blob in the specified range. * @param {object} [options.accessConditions] The access conditions. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information. * @param {boolean} [options.useTransactionalMD5] When set to true, Calculate and send/validate content MD5 for transactions. * @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading blobs. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the blob information. * `response` will contain information related to this operation. * @return {SpeedSummary} * */ BlobService.prototype._getBlobToLocalFile = function (container, blob, localFileName, optionsOrCallback, callback) { var options; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { options = o; callback = c; }); options.speedSummary = options.speedSummary || new SpeedSummary(blob); var writeStream = fs.createWriteStream(localFileName, { 'highWaterMark': BlobConstants.MAX_QUEUED_WRITE_DISK_BUFFER_SIZE }); this.getBlobToStream(container, blob, writeStream, options, function (error, responseBlob, response) { if (error) { if (azureutil.pathExistsSync(localFileName)) { // make sure writeStream is closed / destroyed to avoid locking issues if (writeStream.close) { writeStream.close(); } // If the download failed from the beginning, remove the file. fs.unlink(localFileName, function () { callback(error, responseBlob, response); }); return; } } callback(error, responseBlob, response); }); return options.speedSummary; }; /** * Lists a segment containing a collection of blob items whose names begin with the specified prefix in the container. * @ignore * @this {BlobService} * @param {string} container The container name. * @param {string} prefix The prefix of the blob name. * @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation. * @param {ListBlobTypes} listBlobType Specifies the item type of the results. * @param {object} [options] The request options. * @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.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 {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs]The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information * if an error occurs; otherwise `result` will contain * the entries of blobs and the continuation token for the next listing operation. * `response` will contain information related to this operation. */ BlobService.prototype._listBlobsOrDircotriesSegmentedWithPrefix = function (container, prefix, currentToken, listBlobType, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('listBlobsSegmented', function (v) { v.string(container, 'container'); v.containerNameIsValid(container); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.get(container) .withQueryOption(QueryStringConstants.RESTYPE, 'container') .withQueryOption(QueryStringConstants.COMP, 'list') .withQueryOption(QueryStringConstants.MAX_RESULTS, options.maxResults) .withQueryOptions(options, QueryStringConstants.DELIMITER, QueryStringConstants.INCLUDE); if (!azureutil.objectIsNull(currentToken)) { webResource.withQueryOption(QueryStringConstants.MARKER, currentToken.nextMarker); } webResource.withQueryOption(QueryStringConstants.PREFIX, prefix); options.requestLocationMode = azureutil.getNextListingLocationMode(currentToken); var processResponseCallback = function (responseObject, next) { responseObject.listBlobsResult = null; if (!responseObject.error) { responseObject.listBlobsResult = { entries: null, continuationToken: null }; responseObject.listBlobsResult.entries = []; var results = []; if (listBlobType == BlobConstants.ListBlobTypes.Directory && responseObject.response.body.EnumerationResults.Blobs.BlobPrefix) { results = responseObject.response.body.EnumerationResults.Blobs.BlobPrefix; if (!_.isArray(results)) { results = [results]; } } else if (listBlobType == BlobConstants.ListBlobTypes.Blob && responseObject.response.body.EnumerationResults.Blobs.Blob) { results = responseObject.response.body.EnumerationResults.Blobs.Blob; if (!_.isArray(results)) { results = [results]; } } results.forEach(function (currentBlob) { var blobResult = BlobResult.parse(currentBlob); responseObject.listBlobsResult.entries.push(blobResult); }); if (responseObject.response.body.EnumerationResults.NextMarker) { responseObject.listBlobsResult.continuationToken = { nextMarker: null, targetLocation: null }; responseObject.listBlobsResult.continuationToken.nextMarker = responseObject.response.body.EnumerationResults.NextMarker; responseObject.listBlobsResult.continuationToken.targetLocation = responseObject.targetLocation; } } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.listBlobsResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Create a new blob. * @ignore * * @this {BlobService} * @param {string} container The container name. * @param {string} blob The blob name. * @param (BlobType) blobType The blob type. * @param {int} size The blob size. * @param {object} [options] The request options. * @param {errorOrResult} callback The callback which operates on the specific blob. */ BlobService.prototype._createBlob = function (container, blob, blobType, size, options, creationCallback) { if (blobType == BlobConstants.BlobTypes.APPEND) { this.createOrReplaceAppendBlob(container, blob, options, function (createError, createResponse) { creationCallback(createError, null, createResponse); }); } else if (blobType == BlobConstants.BlobTypes.PAGE) { this.createPageBlob(container, blob, size, options, function (createError) { creationCallback(createError); }); } else if (blobType == BlobConstants.BlobTypes.BLOCK) { creationCallback(); } }; /** * The callback for {BlobService~getBlobToText}. * @typedef {function} BlobService~blobToText * @param {object} error If an error occurs, the error information. * @param {string} text The text returned from the blob. * @param {object} blockBlob Information about the blob. * @param {object} response Information related to this operation. */ BlobService.SpeedSummary = SpeedSummary; module.exports = BlobService;