// // 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 _ = require('underscore'); var extend = require('extend'); var crypto = require('crypto'); var path = require('path'); var azureCommon = require('./../../common/common'); var azureutil = azureCommon.util; var SR = azureCommon.SR; var validate = azureCommon.validate; var SpeedSummary = azureCommon.SpeedSummary; var StorageServiceClient = azureCommon.StorageServiceClient; var WebResource = azureCommon.WebResource; // Constants var Constants = azureCommon.Constants; var FileConstants = Constants.FileConstants; var HeaderConstants = Constants.HeaderConstants; var HttpConstants = Constants.HttpConstants; var QueryStringConstants = Constants.QueryStringConstants; // 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; var FileRangeStream = require('./internal/filerangestream'); // Models requires var ShareResult = require('./models/shareresult'); var DirectoryResult = require('./models/directoryresult'); var FileResult = require('./models/fileresult'); var AclResult = azureCommon.AclResult; /** * Creates a new FileService 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 FileService class is used to perform operations on the Microsoft Azure File Service. * The File Service provides storage for binary large objects, and provides functions for working with data stored in files. * * For more information on the File Service, as well as task focused information on using it in a Node.js application, see * [How to Use the File Service from Node.js](http://azure.microsoft.com/en-us/documentation/articles/storage-nodejs-how-to-use-file-storage/). * The following defaults can be set on the file service. * defaultTimeoutIntervalInMs The default timeout interval, in milliseconds, to use for request made via the file service. * defaultMaximumExecutionTimeInMs The default maximum execution time across all potential retries, for requests made via the file service. * defaultLocationMode The default location mode for requests made via the file service. * parallelOperationThreadCount The number of parallel operations that may be performed when uploading a file. * useNagleAlgorithm Determines whether the Nagle algorithm is used for requests made via the file 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 FileService(storageAccountOrConnectionString, storageAccessKey, host, sasToken) { var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host, sasToken); FileService['super_'].call(this, storageServiceSettings._name, storageServiceSettings._key, storageServiceSettings._fileEndpoint, storageServiceSettings._usePathStyleUri, storageServiceSettings._sasToken); this.singleFileThresholdInBytes = FileConstants.DEFAULT_SINGLE_FILE_GET_THRESHOLD_IN_BYTES; this.parallelOperationThreadCount = Constants.DEFAULT_PARALLEL_OPERATION_THREAD_COUNT; } util.inherits(FileService, StorageServiceClient); // Utility methods /** * Create resource name * @ignore * * @param {string} share Share name * @param {string} [directory] Directory name * @param {string} [file] File name * @return {string} The encoded resource name. */ function createResourceName(share, directory, file, forSAS) { var encode = function(name) { if (name && !forSAS) { name = encodeURIComponent(name); name = name.replace(/%2F/g, '/'); name = name.replace(/%5C/g, '/'); name = name.replace(/\+/g, '%20'); } return name; }; var name = share; if (directory) { // if directory does not start with '/', add it if (directory[0] !== '/') { name += ('/'); } name += encode(directory); } if (file) { // if the current path does not end with '/', add it if (name[name.length - 1] !== '/') { name += ('/'); } name += encode(file); } return path.normalize(name).replace(/\\/g, '/'); } // File service methods /** * Gets the properties of a storage account's File service, including Azure Storage Analytics. * * @this {FileService} * @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. */ FileService.prototype.getServiceProperties = function (optionsOrCallback, callback) { return this.getAccountServiceProperties(optionsOrCallback, callback); }; /** * Sets the properties of a storage account's File 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 {FileService} * @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. */ FileService.prototype.setServiceProperties = function (serviceProperties, optionsOrCallback, callback) { return this.setAccountServiceProperties(serviceProperties, optionsOrCallback, callback); }; // Share methods /** * Lists a segment containing a collection of share items under the specified account. * * @this {FileService} * @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 shares to return per call to Azure storage. * @param {string} [options.include] Include this parameter to specify that the share'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 shares and the `continuationToken` is used for the next listing operation. * `response` will contain information related to this operation. */ FileService.prototype.listSharesSegmented = function (currentToken, optionsOrCallback, callback) { this.listSharesSegmentedWithPrefix(null /* prefix */, currentToken, optionsOrCallback, callback); }; /** * Lists a segment containing a collection of share items whose names begin with the specified prefix under the specified account. * * @this {FileService} * @param {string} prefix The prefix of the share 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 shares whose name begins with the specified prefix. * @param {int} [options.maxResults] Specifies the maximum number of shares to return per call to Azure storage. * @param {string} [options.include] Include this parameter to specify that the share'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 shares and the `continuationToken` is used for the next listing operation. * `response` will contain information related to this operation. */ FileService.prototype.listSharesSegmentedWithPrefix = function (prefix, currentToken, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('listShares', 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.listSharesResult = null; if (!responseObject.error) { responseObject.listSharesResult = { entries: null, continuationToken: null }; responseObject.listSharesResult.entries = []; var shares = []; if (responseObject.response.body.EnumerationResults.Shares && responseObject.response.body.EnumerationResults.Shares.Share) { shares = responseObject.response.body.EnumerationResults.Shares.Share; if (!_.isArray(shares)) { shares = [shares]; } } shares.forEach(function (currentShare) { var shareResult = ShareResult.parse(currentShare); responseObject.listSharesResult.entries.push(shareResult); }); if (responseObject.response.body.EnumerationResults.NextMarker) { responseObject.listSharesResult.continuationToken = { nextMarker: null, targetLocation: null }; responseObject.listSharesResult.continuationToken.nextMarker = responseObject.response.body.EnumerationResults.NextMarker; responseObject.listSharesResult.continuationToken.targetLocation = responseObject.targetLocation; } } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.listSharesResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Checks whether or not a share exists on the service. * * @this {FileService} * @param {string} share The share 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 share exists, or false if the share does not exist. * `response` will contain information related to this operation. */ FileService.prototype.doesShareExist = function (share, optionsOrCallback, callback) { this._doesShareExist(share, false, optionsOrCallback, callback); }; /** * Creates a new share under the specified account. * If a share with the same name already exists, the operation fails. * * @this {FileService} * @param {string} share The share name. * @param {object} [options] The request options. * @param {int} [options.quota] Specifies the maximum size of the share, in gigabytes. * @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 {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 share information. * `response` will contain information related to this operation. */ FileService.prototype.createShare = function (share, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createShare', function (v) { v.string(share, 'share'); v.shareNameIsValid(share); v.shareQuotaIsValid(userOptions.quota); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.put(share) .withQueryOption(QueryStringConstants.RESTYPE, 'share') .withHeader(HeaderConstants.SHARE_QUOTA, options.quota); webResource.addOptionalMetadataHeaders(options.metadata); var processResponseCallback = function (responseObject, next) { responseObject.shareResult = null; if (!responseObject.error) { responseObject.shareResult = new ShareResult(share); responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers); if (options.metadata) { responseObject.shareResult.metadata = options.metadata; } } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.shareResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Creates a new share under the specified account if the share does not exists. * * @this {FileService} * @param {string} share The share 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 {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 share was created, or false if the share * already exists. * `response` will contain information related to this operation. * * @example * var azure = require('azure-storage'); * var FileService = azure.createFileService(); * FileService.createShareIfNotExists('taskshare', function(error) { * if(!error) { * // Share created or already existed * } * }); */ FileService.prototype.createShareIfNotExists = function (share, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createShareIfNotExists', function (v) { v.string(share, 'share'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var self = this; self._doesShareExist(share, true, options, function(error, exists, response) { if(error){ callback(error, exists, response); } else if (exists) { response.isSuccessful = true; callback(error, false, response); } else { self.createShare(share, options, function (createError, responseShare, createResponse) { var created; if(!createError){ created = true; } else if (createError && createError.statusCode === HttpConstants.HttpResponseCodes.Conflict && createError.code === Constants.FileErrorCodeStrings.SHARE_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 share and its properties from a specified account. * * @this {FileService} * @param {string} share The share 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 contain * information for the share. * `response` will contain information related to this operation. */ FileService.prototype.getShareProperties = function (share, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getShareProperties', function (v) { v.string(share, 'share'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.head(share) .withQueryOption(QueryStringConstants.RESTYPE, 'share'); //options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY; var self = this; var processResponseCallback = function (responseObject, next) { responseObject.shareResult = null; if (!responseObject.error) { responseObject.shareResult = new ShareResult(share); responseObject.shareResult.metadata = self.parseMetadataHeaders(responseObject.response.headers); responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.shareResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Sets the properties for the specified share. * * @this {FileService} * @param {string} share The share name. * @param {object} [properties] The share properties to set. * @param {string|int} [properties.quota] Specifies the maximum size of the share, in gigabytes. * @param {object} [options] The request options. * @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 file. * `response` will contain information related to this operation. */ FileService.prototype.setShareProperties = function (share, properties, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('setShareProperties', function (v) { v.string(share, 'share'); v.shareNameIsValid(share); v.shareQuotaIsValid(userOptions.quota); v.callback(callback); }); var options = extend(true, properties, userOptions); var resourceName = createResourceName(share); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.RESTYPE, 'share') .withQueryOption(QueryStringConstants.COMP, 'properties') .withHeader(HeaderConstants.SHARE_QUOTA, options.quota); FileResult.setProperties(webResource, options); var processResponseCallback = function (responseObject, next) { responseObject.shareResult = null; if (!responseObject.error) { responseObject.shareResult = new ShareResult(share); responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.shareResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Gets the share statistics for a share. * * @this {FileService} * @param {string} share The share 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 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. */ FileService.prototype.getShareStats = function (share, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getShareStats', function (v) { v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(share); var webResource = WebResource.get(resourceName) .withQueryOption(QueryStringConstants.RESTYPE, 'share') .withQueryOption(QueryStringConstants.COMP, 'stats'); var processResponseCallback = function (responseObject, next) { responseObject.shareResult = null; if (!responseObject.error) { responseObject.shareResult = ShareResult.parse(responseObject.response.body, share); responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers); } // function to be called after all filters var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.shareResult, returnObject.response); }; // call the first filter next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Returns all user-defined metadata for the share. * * @this {FileService} * @param {string} share The share 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 contain * information for the share. * `response` will contain information related to this operation. */ FileService.prototype.getShareMetadata = function (share, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getShareMetadata', function (v) { v.string(share, 'share'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.head(share) .withQueryOption(QueryStringConstants.RESTYPE, 'share') .withQueryOption(QueryStringConstants.COMP, 'metadata'); var self = this; var processResponseCallback = function (responseObject, next) { responseObject.shareResult = null; if (!responseObject.error) { responseObject.shareResult = new ShareResult(share); responseObject.shareResult.metadata = self.parseMetadataHeaders(responseObject.response.headers); responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.shareResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Sets the share's metadata. * * Calling the Set Share Metadata operation overwrites all existing metadata that is associated with the share. * It's not possible to modify an individual name/value pair. * * @this {FileService} * @param {string} share The share name. * @param {object} metadata The metadata key/value pairs. * @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. */ FileService.prototype.setShareMetadata = function (share, metadata, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('setShareMetadata', function (v) { v.string(share, 'share'); v.object(metadata, 'metadata'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.put(share) .withQueryOption(QueryStringConstants.RESTYPE, 'share') .withQueryOption(QueryStringConstants.COMP, 'metadata'); webResource.addOptionalMetadataHeaders(metadata); var processResponseCallback = function (responseObject, next) { responseObject.shareResult = null; if (!responseObject.error) { responseObject.shareResult = new ShareResult(share); responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.shareResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Gets the share's ACL. * * @this {FileService} * @param {string} share The share 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 contain * information for the share. * `response` will contain information related to this operation. */ FileService.prototype.getShareAcl = function (share, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getShareAcl', function (v) { v.string(share, 'share'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.get(share) .withQueryOption(QueryStringConstants.RESTYPE, 'share') .withQueryOption(QueryStringConstants.COMP, 'acl'); options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY; var processResponseCallback = function (responseObject, next) { responseObject.shareResult = null; if (!responseObject.error) { responseObject.shareResult = new ShareResult(share); responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers); responseObject.shareResult.signedIdentifiers = AclResult.parse(responseObject.response.body); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.shareResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Updates the share's ACL. * * @this {FileService} * @param {string} share The share name. * @param {object} signedIdentifiers The signed identifiers. Signed identifiers must be in an array. * @param {object} [options] The request options. * @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 share. * `response` will contain information related to this operation. */ FileService.prototype.setShareAcl = function (share, signedIdentifiers, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('setShareAcl', function (v) { v.string(share, 'share'); v.shareNameIsValid(share); 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(share) .withQueryOption(QueryStringConstants.RESTYPE, 'share') .withQueryOption(QueryStringConstants.COMP, 'acl') .withHeader(HeaderConstants.CONTENT_LENGTH, !azureutil.objectIsNull(policies) ? Buffer.byteLength(policies) : 0) .withBody(policies); var processResponseCallback = function (responseObject, next) { responseObject.shareResult = null; if (!responseObject.error) { responseObject.shareResult = new ShareResult(share); responseObject.shareResult.getPropertiesFromHeaders(responseObject.response.headers); if (signedIdentifiers) { responseObject.shareResult.signedIdentifiers = signedIdentifiers; } } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.shareResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, webResource.body, options, processResponseCallback); }; /** * Marks the specified share for deletion. * The share and any files contained within it are later deleted during garbage collection. * * @this {FileService} * @param {string} share The share 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 {errorOrResponse} callback `error` will contain information * if an error occurs; otherwise * `response` will contain information related to this operation. */ FileService.prototype.deleteShare = function (share, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('deleteShare', function (v) { v.string(share, 'share'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.del(share) .withQueryOption(QueryStringConstants.RESTYPE, 'share'); 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 share for deletion if it exists. * The share and any files contained within it are later deleted during garbage collection. * * @this {FileService} * @param {string} share The share 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 share exists and was deleted, or false if the share * did not exist. * `response` will contain information related to this operation. */ FileService.prototype.deleteShareIfExists = function (share, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('deleteShareIfExists', function (v) { v.string(share, 'share'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var self = this; self._doesShareExist(share, true, options, function (error, exists, response) { if(error){ callback(error, exists, response); } else if (!exists) { response.isSuccessful = true; callback(error, false, response); } else { self.deleteShare(share, options, function (deleteError, deleteResponse) { var deleted; if (!deleteError){ deleted = true; } else if (deleteError && deleteError.statuscode === HttpConstants.HttpResponseCodes.NotFound && deleteError.code === Constants.FileErrorCodeStrings.SHARE_NOT_FOUND) { // If it was deleted already, there was no actual error. deleted = false; deleteError = null; deleteResponse.isSuccessful = true; } callback(deleteError, deleted, deleteResponse); }); } }); }; // Directory methods /** * Checks whether or not a directory exists on the service. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @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 directory exists, or false if the directory does not exist. * `response` will contain information related to this operation. */ FileService.prototype.doesDirectoryExist = function (share, directory, optionsOrCallback, callback) { this._doesDirectoryExist(share, directory, false, optionsOrCallback, callback); }; /** * Creates a new directory under the specified account. * If a directory with the same name already exists, the operation fails. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory 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 contain * the directory information. * `response` will contain information related to this operation. */ FileService.prototype.createDirectory = function (share, directory, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createDirectory', function (v) { v.string(share, 'share'); v.string(directory, 'directory'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.put(createResourceName(share, directory)) .withQueryOption(QueryStringConstants.RESTYPE, 'directory'); webResource.addOptionalMetadataHeaders(options.metadata); var processResponseCallback = function (responseObject, next) { responseObject.directoryResult = null; if (!responseObject.error) { responseObject.directoryResult = new DirectoryResult(directory); responseObject.directoryResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.directoryResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Creates a new directory under the specified account if the directory does not exists. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory 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 directory was created, or false if the directory * already exists. * `response` will contain information related to this operation. * * @example * var azure = require('azure-storage'); * var FileService = azure.createFileService(); * FileService.createDirectoryIfNotExists('taskshare', taskdirectory', function(error) { * if(!error) { * // Directory created or already existed * } * }); */ FileService.prototype.createDirectoryIfNotExists = function (share, directory, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createDirectoryIfNotExists', function (v) { v.string(share, 'share'); v.string(directory, 'directory'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var self = this; self._doesDirectoryExist(share, directory, true, options, function(error, exists, response) { if(error){ callback(error, exists, response); } else if (exists) { response.isSuccessful = true; callback(error, false, response); } else { self.createDirectory(share, directory, options, function (createError, responseDirectory, createResponse) { var created; if(!createError){ created = true; } else if (createError && createError.statusCode === HttpConstants.HttpResponseCodes.Conflict && createError.code === Constants.StorageErrorCodeStrings.RESOURCE_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 directory and its properties from a specified account. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @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 * information for the directory. * `response` will contain information related to this operation. */ FileService.prototype.getDirectoryProperties = function (share, directory, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getDirectoryProperties', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.head(createResourceName(share, directory)) .withQueryOption(QueryStringConstants.RESTYPE, 'directory'); var self = this; var processResponseCallback = function (responseObject, next) { responseObject.directoryResult = null; if (!responseObject.error) { responseObject.directoryResult = new DirectoryResult(directory); responseObject.directoryResult.metadata = self.parseMetadataHeaders(responseObject.response.headers); responseObject.directoryResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.directoryResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Marks the specified directory for deletion. The directory must be empty before it can be deleted. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory 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 {errorOrResponse} callback `error` will contain information * if an error occurs; otherwise * `response` will contain information related to this operation. */ FileService.prototype.deleteDirectory = function (share, directory, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('deleteDirectory', function (v) { v.string(share, 'share'); v.string(directory, 'directory'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.del(createResourceName(share, directory)) .withQueryOption(QueryStringConstants.RESTYPE, 'directory'); 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 directory for deletion if it exists. The directory must be empty before it can be deleted. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory 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 directory exists and was deleted, or false if the directory * did not exist. * `response` will contain information related to this operation. */ FileService.prototype.deleteDirectoryIfExists = function (share, directory, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('deleteDirectoryIfExists', function (v) { v.string(share, 'share'); v.string(directory, 'directory'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var self = this; self._doesDirectoryExist(share, directory, true, options, function(error, exists, response) { if(error){ callback(error, exists, response); } else if (!exists) { response.isSuccessful = true; callback(error, false, response); } else { self.deleteDirectory(share, directory, options, function (deleteError, deleteResponse) { var deleted; if (!deleteError){ deleted = true; } else if (deleteError && deleteError.statuscode === HttpConstants.HttpResponseCodes.NotFound && deleteError.code === Constants.StorageErrorCodeStrings.RESOURCE_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 file items in the directory. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base 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 files 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.files, entries.directories and the continuationToken for the next listing operation. * `response` will contain information related to this operation. */ FileService.prototype.listFilesAndDirectoriesSegmented = function (share, directory, currentToken, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('listFilesSegmented', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.get(createResourceName(share, directory)) .withQueryOption(QueryStringConstants.RESTYPE, 'directory') .withQueryOption(QueryStringConstants.COMP, 'list') .withQueryOption(QueryStringConstants.MAX_RESULTS, options.maxResults); if (!azureutil.objectIsNull(currentToken)) { webResource.withQueryOption(QueryStringConstants.MARKER, currentToken.nextMarker); } var processResponseCallback = function (responseObject, next) { responseObject.listResult = null; if (!responseObject.error) { responseObject.listResult = { entries: null, continuationToken: null }; responseObject.listResult.entries = {}; responseObject.listResult.entries.files = []; responseObject.listResult.entries.directories = []; var files = []; var directories = []; // parse files if (responseObject.response.body.EnumerationResults.Entries.File) { files = responseObject.response.body.EnumerationResults.Entries.File; if (!_.isArray(files)) { files = [ files ]; } } files.forEach(function (currentFile) { var fileResult = FileResult.parse(currentFile); responseObject.listResult.entries.files.push(fileResult); }); // parse directories if (responseObject.response.body.EnumerationResults.Entries.Directory) { directories = responseObject.response.body.EnumerationResults.Entries.Directory; if (!_.isArray(directories)) { directories = [ directories ]; } } directories.forEach(function (currentDirectory) { var directoryResult = DirectoryResult.parse(currentDirectory); responseObject.listResult.entries.directories.push(directoryResult); }); // parse continuation token if(responseObject.response.body.EnumerationResults.NextMarker) { responseObject.listResult.continuationToken = { nextMarker: null, targetLocation: null }; responseObject.listResult.continuationToken.nextMarker = responseObject.response.body.EnumerationResults.NextMarker; responseObject.listResult.continuationToken.targetLocation = responseObject.targetLocation; } } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.listResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Returns all user-defined metadata for the specified directory. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @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 file. * `response` will contain information related to this operation. */ FileService.prototype.getDirectoryMetadata = function (share, directory, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getDirectoryMetadata', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(share, directory); var webResource = WebResource.head(resourceName) .withQueryOption(QueryStringConstants.RESTYPE, 'directory') .withQueryOption(QueryStringConstants.COMP, 'metadata'); var self = this; var processResponseCallback = function (responseObject, next) { responseObject.directoryResult = null; if (!responseObject.error) { responseObject.directoryResult = new DirectoryResult(directory); responseObject.directoryResult.metadata = self.parseMetadataHeaders(responseObject.response.headers); responseObject.directoryResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.directoryResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Sets user-defined metadata for the specified directory as one or more name-value pairs * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {object} metadata The metadata key/value pairs. * @param {object} [options] The request options. * @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 file. * `response` will contain information related to this operation. */ FileService.prototype.setDirectoryMetadata = function (share, directory, metadata, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('setDirectoryMetadata', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.shareNameIsValid(share); v.object(metadata, 'metadata'); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(share, directory); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.RESTYPE, 'directory') .withQueryOption(QueryStringConstants.COMP, 'metadata'); webResource.addOptionalMetadataHeaders(metadata); var processResponseCallback = function (responseObject, next) { responseObject.directoryResult = null; if (!responseObject.error) { responseObject.directoryResult = new DirectoryResult(directory); responseObject.directoryResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.directoryResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; // File methods /** * Retrieves a shared access signature token. * * @this {FileService} * @param {string} share The share name. * @param {string} [directory] The directory name. Use '' to refer to the base directory. * @param {string} [file] The file 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 file 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 "?". */ FileService.prototype.generateSharedAccessSignature = function (share, directory, file, sharedAccessPolicy, headers) { // check if the FileService 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 share name. File name is optional. validate.validateArgs('generateSharedAccessSignature', function (v) { v.string(share, 'share'); v.shareNameIsValid(share); v.object(sharedAccessPolicy, 'sharedAccessPolicy'); }); var resourceType = FileConstants.ResourceTypes.SHARE; if (file) { validate.validateArgs('generateSharedAccessSignature', function (v) { v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); }); resourceType = FileConstants.ResourceTypes.FILE; } else { directory = ''; // If file is not set, directory is not a part of the string to sign. } 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(share, directory, file, true); return this.storageCredentials.generateSignedQueryString(Constants.ServiceType.File, resourceName, sharedAccessPolicy, null, { headers: headers, resourceType: resourceType }); }; /** * Retrieves a file or directory URL. * * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} [file] The file name. File names may not start or end with the delimiter '/'. * @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 FileService = azure.createFileService(); * var url = FileService.getUrl(shareName, directoryName, fileName, sasToken, true); */ FileService.prototype.getUrl = function (share, directory, file, sasToken, primary) { validate.validateArgs('getUrl', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.shareNameIsValid(share); }); var host; if(!azureutil.objectIsNull(primary) && primary === false) { host = this.host.secondaryHost; } else { host = this.host.primaryHost; } host = azureutil.trimPortFromUri(host); var name = createResourceName(share, directory, file); return url.resolve(host, url.format({pathname: this._getPath('/' + name), query: qs.parse(sasToken)})); }; /** * Returns all user-defined metadata, standard HTTP properties, and system properties for the file. * It does not return or modify the content of the file. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @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 * information about the file. * `response` will contain information related to this operation. */ FileService.prototype.getFileProperties = function (share, directory, file, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getFileProperties', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(share, directory, file); var webResource = WebResource.head(resourceName); var self = this; var processResponseCallback = function (responseObject, next) { responseObject.fileResult = null; if (!responseObject.error) { responseObject.fileResult = new FileResult(share, directory, file); responseObject.fileResult.metadata = self.parseMetadataHeaders(responseObject.response.headers); responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers, true); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.fileResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Returns all user-defined metadata for the specified file. * It does not modify or return the content of the file. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @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 file. * `response` will contain information related to this operation. */ FileService.prototype.getFileMetadata = function (share, directory, file, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getFileMetadata', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(share, directory, file); var webResource = WebResource.head(resourceName) .withQueryOption(QueryStringConstants.COMP, 'metadata'); var self = this; var processResponseCallback = function (responseObject, next) { responseObject.fileResult = null; if (!responseObject.error) { responseObject.fileResult = new FileResult(share, directory, file); responseObject.fileResult.metadata = self.parseMetadataHeaders(responseObject.response.headers); responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.fileResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Sets user-defined properties for the specified file. * It does not modify or return the content of the file. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @param {object} [properties] The file properties to set. * @param {string} [properties.contentType] The MIME content type of the file. The default type is application/octet-stream. * @param {string} [properties.contentEncoding] The content encodings that have been applied to the file. * @param {string} [properties.contentLanguage] The natural languages used by this resource. * @param {string} [properties.contentMD5] The MD5 hash of the file content. * @param {string} [properties.cacheControl] The file's cache control. * @param {string} [properties.contentDisposition] The file's content disposition. * @param {string} [properties.contentLength] Resizes a file to the specified size. If the specified byte value is less than the current size of the file, * then all ranges above the specified byte value are cleared. * @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 * information about the file. * `response` will contain information related to this operation. */ FileService.prototype.setFileProperties = function (share, directory, file, properties, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('setFileProperties', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, properties, userOptions); var resourceName = createResourceName(share, directory, file); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.COMP, 'properties'); FileResult.setProperties(webResource, options); var processResponseCallback = function(responseObject, next) { responseObject.fileResult = null; if (!responseObject.error) { responseObject.fileResult = new FileResult(share, directory, file); responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function(returnObject) { callback(returnObject.error, returnObject.fileResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Sets user-defined metadata for the specified file as one or more name-value pairs * It does not modify or return the content of the file. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @param {object} metadata The metadata key/value pairs. * @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 * information on the file. * `response` will contain information related to this operation. */ FileService.prototype.setFileMetadata = function (share, directory, file, metadata, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('setFileMetadata', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.shareNameIsValid(share); v.object(metadata, 'metadata'); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(share, directory, file); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.COMP, 'metadata'); webResource.addOptionalMetadataHeaders(metadata); var processResponseCallback = function (responseObject, next) { responseObject.fileResult = null; if (!responseObject.error) { responseObject.fileResult = new FileResult(share, directory, file); responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.fileResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Resizes a file. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @param {String} size The size of the file, in bytes. * @param {object} [options] The request options. * @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 file. * `response` will contain information related to this operation. */ FileService.prototype.resizeFile = function (share, directory, file, size, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('resizeFile', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.shareNameIsValid(share); v.value(size); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(share, directory, file); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.COMP, 'properties'); webResource.withHeader(HeaderConstants.FILE_CONTENT_LENGTH, size); var processResponseCallback = function(responseObject, next) { responseObject.fileResult = null; if (!responseObject.error) { responseObject.fileResult = new FileResult(share, directory, file); responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function(returnObject) { callback(returnObject.error, returnObject.fileResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Checks whether or not a file exists on the service. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @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 file exists, or false if the file does not exist. * `response` will contain information related to this operation. */ FileService.prototype.doesFileExist = function (share, directory, file, optionsOrCallback, callback) { this._doesFileExist(share, directory, file, false, optionsOrCallback, callback); }; /** * Creates a file of the specified length. If the file already exists on the service, it will be overwritten. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @param {int} length The length of the file in bytes. * @param {object} [options] The request options. * @param {object} [options.metadata] The metadata key/value pairs. * @param {string} [options.contentType] The MIME content type of the file. The default type is application/octet-stream. * @param {string} [options.contentEncoding] The content encodings that have been applied to the file. * @param {string} [options.contentLanguage] The natural languages used by this resource. * @param {string} [options.contentMD5] The MD5 hash of the file content. * @param {string} [options.cacheControl] The file service stores this value but does not use or modify it. * @param {string} [options.contentDisposition] The file's content disposition. (x-ms-File-content-disposition) * @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 directory information. * `response` will contain information related to this operation. */ FileService.prototype.createFile = function (share, directory, file, length, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createFile', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.shareNameIsValid(share); v.value(length); v.callback(callback); }); var resourceName = createResourceName(share, directory, file); var options = extend(true, {}, userOptions); var webResource = WebResource.put(resourceName) .withHeader(HeaderConstants.TYPE, 'file') .withHeader(HeaderConstants.FILE_CONTENT_LENGTH, length); FileResult.setProperties(webResource, options); var processResponseCallback = function(responseObject, next) { responseObject.fileResult = null; if (!responseObject.error) { responseObject.fileResult = new FileResult(share, directory, file); responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function(returnObject) { callback(returnObject.error, returnObject.fileResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Marks the specified file for deletion. The file is later deleted during garbage collection. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @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; `response` will contain information related to this operation. */ FileService.prototype.deleteFile = function (share, directory, file, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('deleteFile', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(share, directory, file); var webResource = WebResource.del(resourceName); 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 file for deletion if it exists. The file is later deleted during garbage collection. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @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 file was deleted, or false if the file * does not exist. * `response` will contain information related to this operation. */ FileService.prototype.deleteFileIfExists = function (share, directory, file, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('deleteFileIfExists', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var self = this; self._doesFileExist(share, directory, file, true, options, function(error, exists, response) { if(error){ callback(error, exists, response); } else if (!exists) { response.isSuccessful = true; callback(error, false, response); } else { self.deleteFile(share, directory, file, options, function (deleteError, deleteResponse) { var deleted; if (!deleteError){ deleted = true; } else if (deleteError && deleteError.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound && deleteError.code === Constants.FileErrorCodeStrings.FILE_NOT_FOUND) { // If it was deleted already, there was no actual error. deleted = false; deleteError = null; deleteResponse.isSuccessful = true; } callback(deleteError, deleted, deleteResponse); }); } }); }; /** * Downloads a file into a text string. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @param {object} [options] The request options. * @param {int} [options.rangeStart] The range start. * @param {int} [options.rangeEnd] The range end. * @param {boolean} [options.disableContentMD5Validation] When set to true, MD5 validation will be disabled when downloading files. * @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 {FileService~FileToText} callback `error` will contain information * if an error occurs; otherwise `text` will contain the file contents, * and `file` will contain the file information. * `response` will contain information related to this operation. */ FileService.prototype.getFileToText = function (share, directory, file, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getFileToText', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(share, directory, file); var webResource = WebResource.get(resourceName) .withRawResponse(); FileResult.setHeaders(webResource, options); this._setRangeContentMD5Header(webResource, options); var self = this; var processResponseCallback = function (responseObject, next) { responseObject.text = null; responseObject.fileResult = null; if (!responseObject.error) { responseObject.fileResult = new FileResult(share, directory, file); responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers, true); responseObject.fileResult.metadata = self.parseMetadataHeaders(responseObject.response.headers); responseObject.text = responseObject.response.body; self._validateLengthAndMD5(options, responseObject); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.text, returnObject.fileResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Downloads an Azure file into a file. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @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 files. * Parallel download and speed summary won't work with this option on. * @param {SpeedSummary} [options.speedSummary] The download tracker objects. * @param {string} [options.rangeStart] Return only the bytes of the file in the specified range. * @param {string} [options.rangeEnd] Return only the bytes of the file 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 files. * @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 file information. * `response` will contain information related to this operation. * @return {SpeedSummary} * * @example * var azure = require('azure-storage'); * var FileService = azure.createFileService(); * FileService.getFileToLocalFile('taskshare', taskdirectory', 'task1', 'task1-download.txt', function(error, serverFile) { * if(!error) { * // file available in serverFile.file variable * } */ FileService.prototype.getFileToLocalFile = function (share, directory, file, localFileName, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); userOptions.speedSummary = userOptions.speedSummary || new SpeedSummary(file); validate.validateArgs('getFileToLocalFile', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.string(localFileName, 'localFileName'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var writeStream = fs.createWriteStream(localFileName); this.getFileToStream(share, directory, file, writeStream, options, function (error, responseFile, response) { if (error) { // make sure writeStream is closed / destroyed to avoid locking issues if (writeStream.close) { writeStream.close(); } if (azureutil.pathExistsSync(localFileName)) { // If the download failed from the beginning, remove the file. fs.unlink(localFileName, function () { callback(error, responseFile, response); return; }); } } callback(error, responseFile, response); }); return options.speedSummary; }; /** * Provides a stream to read from a file. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @param {object} [options] The request options. * @param {string} [options.rangeStart] Return only the bytes of the file in the specified range. * @param {string} [options.rangeEnd] Return only the bytes of the file 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 files. * @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 file information. * `response` will contain information related to this operation. * @return {Stream} * @example * var azure = require('azure-storage'); * var fileService = azure.createFileService(); * var writable = fs.createWriteStream(destinationFileNameTarget); * fileService.createReadStream(shareName, directoryName, fileName).pipe(writable); */ FileService.prototype.createReadStream = function (share, directory, file, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createReadStream', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.shareNameIsValid(share); }); var options = extend(true, {}, userOptions); var readStream = new ChunkStream(options); this.getFileToStream(share, directory, file, readStream, options, function (error, fileResponse, response) { if(error) { readStream.emit('error', error); } if(callback) { callback(error, fileResponse, response); } }); return readStream; }; /** * Downloads a file into a stream. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @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 files. * Parallel download and speed summary won't work with this option on. * @param {SpeedSummary} [options.speedSummary] The download tracker objects. * @param {string} [options.rangeStart] Return only the bytes of the file in the specified range. * @param {string} [options.rangeEnd] Return only the bytes of the file 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 files. * @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 file information. * `response` will contain information related to this operation. * @return {SpeedSummary} * * * @example * var azure = require('azure-storage'); * var FileService = azure.createFileService(); * FileService.getFileToStream('taskshare', taskdirectory', 'task1', fs.createWriteStream('task1-download.txt'), function(error, serverFile) { * if(!error) { * // file available in serverFile.file variable * } * }); */ FileService.prototype.getFileToStream = function (share, directory, file, writeStream, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); userOptions.speedSummary = userOptions.speedSummary || new SpeedSummary(file); validate.validateArgs('getFileToStream', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.object(writeStream, 'writeStream'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var propertiesRequestOptions = { timeoutIntervalInMs : options.timeoutIntervalInMs, accessConditions : options.accessConditions }; if (options.skipSizeCheck) { this._getFileToStream(share, directory, file, writeStream, options, callback); } else { var self = this; this.getFileProperties(share, directory, file, 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.singleFileThresholdInBytes) { options.contentMD5 = properties.contentMD5; self._getFileToRangeStream(share, directory, file, writeStream, options, callback); } else { self._getFileToStream(share, directory, file, writeStream, options, callback); } } }); } return options.speedSummary; }; /** * Lists file ranges. Lists all of the ranges by default, or only the ranges over a specific range of bytes if rangeStart and rangeEnd are specified. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @param {object} [options] The request options. * @param {int} [options.rangeStart] The range start. * @param {int} [options.rangeEnd] The range end. * @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 range information. * `response` will contain information related to this operation. */ FileService.prototype.listRanges = function (share, directory, file, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('listRanges', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.shareNameIsValid(share); v.callback(callback); }); var resourceName = createResourceName(share, directory, file); var options = extend(true, {}, userOptions); var webResource = WebResource.get(resourceName) .withQueryOption(QueryStringConstants.COMP, 'rangelist'); FileResult.setHeaders(webResource, options); var processResponseCallback = function (responseObject, next) { responseObject.ranges = null; if (!responseObject.error) { responseObject.ranges = []; var ranges = []; if (responseObject.response.body.Ranges.Range) { ranges = responseObject.response.body.Ranges.Range; if (!_.isArray(ranges)) { ranges = [ ranges ]; } } ranges.forEach(function (fileRange) { var range = { start: parseInt(fileRange.Start, 10), end: parseInt(fileRange.End, 10) }; responseObject.ranges.push(range); }); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.ranges, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Clears a range. Clears all of the ranges by default, or only the ranges over a specific range of bytes if rangeStart and rangeEnd are specified. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @param {int} rangeStart The range start. * @param {int} rangeEnd The range end. * @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 directory information. * `response` will contain information related to this operation. */ FileService.prototype.clearRange = function (share, directory, file, rangeStart, rangeEnd, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('clearRange', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.shareNameIsValid(share); v.value(rangeStart); v.value(rangeEnd); v.callback(callback); }); var options = extend(true, {}, userOptions); var request = this._updateFilesImpl(share, directory, file, rangeStart, rangeEnd, FileConstants.RangeWriteOptions.CLEAR, options); var processResponseCallback = function(responseObject, next) { responseObject.fileResult = null; if (!responseObject.error) { responseObject.fileResult = new FileResult(share, directory, file); responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function(returnObject) { callback(returnObject.error, returnObject.fileResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(request, null, options, processResponseCallback); }; /** * Updates a range from a stream. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @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 {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 {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 file information. * `response` will contain information related to this operation. */ FileService.prototype.createRangesFromStream = function (share, directory, file, readStream, rangeStart, rangeEnd, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createRangesFromStream', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.object(readStream, 'readStream'); v.shareNameIsValid(share); v.value(rangeStart); v.value(rangeEnd); v.callback(callback); }); var options = extend(true, {}, userOptions); var requiresContentMD5 = azureutil.objectIsNull(options.contentMD5) && options.useTransactionalMD5 === true; var length = (rangeEnd - rangeStart) + 1; if(length > FileConstants.MAX_UPDATE_FILE_SIZE) { throw new Error(SR.INVALID_FILE_RANGE_FOR_UPDATE); } var self = this; if (requiresContentMD5) { azureutil.calculateMD5(readStream, length, options, function(internalBuff) { self._createRanges(share, directory, file, internalBuff, null /* stream */, rangeStart, rangeEnd, options, callback); }); } else { self._createRanges(share, directory, file, null /* text */, readStream, rangeStart, rangeEnd, options, callback); } }; /** * Uploads a file from a text string. If the file already exists on the service, it will be overwritten. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @param {string|object} text The file text, as a string or in a Buffer. * @param {object} [options] The request options. * @param {SpeedSummary} [options.speedSummary] The upload tracker objects; * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeFileContentMD5] Specifies whether the file's ContentMD5 header should be set on uploads. * The default value is false for files. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @param {string} [options.contentType] The MIME content type of the file. The default type is application/octet-stream. * @param {string} [options.contentEncoding] The content encodings that have been applied to the file. * @param {string} [options.contentLanguage] The natural languages used by this resource. * @param {string} [options.contentMD5] The MD5 hash of the file content. * @param {string} [options.cacheControl] The file service stores this value but does not use or modify it. * @param {string} [options.contentDisposition] The file's content disposition. (x-ms-File-content-disposition) * @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 {FileService~FileToText} callback `error` will contain information * if an error occurs; otherwise `text` will contain the file contents, * and `file` will contain the file information. * `response` will contain information related to this operation. */ FileService.prototype.createFileFromText = function (share, directory, file, text, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createFileFromText', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.exists(text, 'text'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var length = Buffer.isBuffer(text) ? text.length : Buffer.byteLength(text); if (length > FileConstants.MAX_UPDATE_FILE_SIZE) { throw new Error(SR.INVALID_FILE_LENGTH); } if(options.storeFileContentMD5 && azureutil.objectIsNull(options.contentMD5)) { options.contentMD5 = azureutil.getContentMd5(text); } var self = this; this.createFile(share, directory, file, length, options, function(error) { if(error) { callback(error); } else { self._createRanges(share, directory, file, text, null, 0, length - 1, options, callback); } }); }; /** * Uploads a file to storage from a local file. If the file already exists on the service, it will be overwritten. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @param (string) localFileName The local path to the file to be uploaded. * @param {object} [options] The request options. * @param {SpeedSummary} [options.speedSummary] The download tracker objects; * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeFileContentMD5] Specifies whether the file's ContentMD5 header should be set on uploads. * The default value is false for files. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @param {string} [options.contentType] The MIME content type of the file. The default type is application/octet-stream. * @param {string} [options.contentEncoding] The content encodings that have been applied to the file. * @param {string} [options.contentLanguage] The natural languages used by this resource. * @param {string} [options.contentMD5] The MD5 hash of the file content. * @param {string} [options.cacheControl] The file service stores this value but does not use or modify it. * @param {string} [options.contentDisposition] The file's content disposition. (x-ms-File-content-disposition) * @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} */ FileService.prototype.createFileFromLocalFile = function (share, directory, file, localFileName, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createFileFromLocalFile', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.string(localFileName, 'localFileName'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); options.speedSummary = options.speedSummary || new SpeedSummary(file); var self = this; fs.stat(localFileName, function(error, stat) { if (error) { callback(error); } else { self.createFile(share, directory, file, stat.size, options, function(error) { if(error) { callback(error); } else { var stream = new FileReadStream(localFileName, {calcContentMd5: options.storeFileContentMD5}); self._createFileFromChunkStream(share, directory, file, stream, stat.size, options, callback); } }); } }); return options.speedSummary; }; /** * Uploads a file from a stream. If the file already exists on the service, it will be overwritten. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @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 {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeFileContentMD5] Specifies whether the file's ContentMD5 header should be set on uploads. * The default value is false for files. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @param {string} [options.contentType] The MIME content type of the file. The default type is application/octet-stream. * @param {string} [options.contentEncoding] The content encodings that have been applied to the file. * @param {string} [options.contentLanguage] The natural languages used by this resource. * @param {string} [options.contentMD5] The MD5 hash of the file content. * @param {string} [options.cacheControl] The file service stores this value but does not use or modify it. * @param {string} [options.contentDisposition] The file's content disposition. (x-ms-File-content-disposition) * @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} */ FileService.prototype.createFileFromStream = function(share, directory, file, stream, streamLength, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createFileFromStream', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.object(stream, 'stream'); v.value(streamLength, 'streamLength'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); options.speedSummary = options.speedSummary || new SpeedSummary(file); stream.pause(); // Immediately pause the stream in order to compatible with Node v0.8 var self = this; this.createFile(share, directory, file, streamLength, options, function(error) { if(error) { callback(error); } else { var chunkStream = new ChunkStreamWithStream(stream, {calcContentMd5: options.storeFileContentMD5}); self._createFileFromChunkStream(share, directory, file, chunkStream, streamLength, options, callback); } }); return options.speedSummary; }; /** * Provides a stream to write to a file. Assumes that the file exists. * If it does not, please create the file using createFile before calling this method or use createWriteStreamNewFile. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @param {object} [options] The request options. * @param {SpeedSummary} [options.speedSummary] The download tracker objects; * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeFileContentMD5] Specifies whether the file's ContentMD5 header should be set on uploads. * The default value is false for files. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @param {string} [options.contentType] The MIME content type of the file. The default type is application/octet-stream. * @param {string} [options.contentEncoding] The content encodings that have been applied to the file. * @param {string} [options.contentLanguage] The natural languages used by this resource. * @param {string} [options.contentMD5] The MD5 hash of the file content. * @param {string} [options.cacheControl] The file service stores this value but does not use or modify it. * @param {string} [options.contentDisposition] The file's content disposition. (x-ms-File-content-disposition) * @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 {Stream} * @example * var azure = require('azure-storage'); * var FileService = azure.createFileService(); * FileService.createFile(shareName, directoryName, fileName, 1024, function (err) { * // Pipe file to a file * var stream = fs.createReadStream(fileNameTarget).pipe(FileService.createWriteStreamToExistingFile(shareName, directoryName, fileName)); * }); */ FileService.prototype.createWriteStreamToExistingFile = function (share, directory, file, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createWriteStreamToExistingFile', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.shareNameIsValid(share); }); var options = extend(true, {}, userOptions); var stream = new ChunkStream({calcContentMd5: options.storeFileContentMD5}); this._createFileFromChunkStream(share, directory, file, stream, null, options, function (error, file, response) { if(error) { stream.emit('error', error); } if (callback) { callback(error, file, response); } }); return stream; }; /** * Provides a stream to write to a file. Creates the file before writing data. * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @param {string} length The file length. * @param {object} [options] The request options. * @param {SpeedSummary} [options.speedSummary] The download tracker objects; * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeFileContentMD5] Specifies whether the file's ContentMD5 header should be set on uploads. * The default value is false for files. * @param {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @param {string} [options.contentType] The MIME content type of the file. The default type is application/octet-stream. * @param {string} [options.contentEncoding] The content encodings that have been applied to the file. * @param {string} [options.contentLanguage] The natural languages used by this resource. * @param {string} [options.contentMD5] The MD5 hash of the file content. * @param {string} [options.cacheControl] The file service stores this value but does not use or modify it. * @param {string} [options.contentDisposition] The file's content disposition. (x-ms-File-content-disposition) * @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 {Stream} * @example * var azure = require('azure-storage'); * var FileService = azure.createFileService(); * var stream = fs.createReadStream(fileNameTarget).pipe(FileService.createWriteStreamToNewFile(shareName, directoryName, fileName)); */ FileService.prototype.createWriteStreamToNewFile = function (share, directory, file, length, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createWriteStreamToNewFile', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.value(length, 'length'); v.shareNameIsValid(share); }); var options = extend(true, {}, userOptions); var stream = new ChunkStream({calcContentMd5: options.storeFileContentMD5}); stream.pause(); var self = this; this.createFile(share, directory, file, length, options, function(error) { if(error) { stream.emit('error', error); callback(error); } else { stream.resume(); self._createFileFromChunkStream(share, directory, file, stream, null, options, function (error, file, response) { if(error) { stream.emit('error', error); } if (callback) { callback(error, file, response); } }); } }); return stream; }; /** * Starts to copy a file to a destination within the storage account. * * @this {FileService} * @param {string} sourceUri The source file or blob URI. * @param {string} targetShare The target share name. * @param {string} targetDirectory The target directory name. * @param {string} targetFile The target file name. * @param {object} [options] The request options. * @param {object} [options.metadata] The target file metadata key/value pairs. * @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 file information. * `response` will contain information related to this operation. */ FileService.prototype.startCopyFile = function (sourceUri, targetShare, targetDirectory, targetFile, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('startCopyFile', function (v) { v.string(targetShare, 'targetShare'); v.stringAllowEmpty(targetDirectory, 'targetDirectory'); v.string(targetFile, 'targetFile'); v.shareNameIsValid(targetShare); v.callback(callback); }); var targetResourceName = createResourceName(targetShare, targetDirectory, targetFile); var options = extend(true, {}, userOptions); var webResource = WebResource.put(targetResourceName) .withHeader(HeaderConstants.COPY_SOURCE, sourceUri) .addOptionalMetadataHeaders(options.metadata); var processResponseCallback = function (responseObject, next) { responseObject.fileResult = null; if (!responseObject.error) { responseObject.fileResult = new FileResult(targetShare, targetDirectory, targetFile); responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers, true); if (options.metadata) { responseObject.fileResult.metadata = options.metadata; } } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.fileResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Abort a file copy operation. * * @this {FileService} * @param {string} share The destination share name. * @param {string} directory The destination directory name. * @param {string} file The destination file name. * @param {string} copyId The copy operation identifier. * @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 file information. * `response` will contain information related to this operation. */ FileService.prototype.abortCopyFile = function (share, directory, file, copyId, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('abortCopyFile', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.shareNameIsValid(share); v.callback(callback); }); var resourceName = createResourceName(share, directory, file); var options = extend(true, {}, userOptions); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.COPY_ID, copyId) .withQueryOption(QueryStringConstants.COMP, 'copy') .withHeader(HeaderConstants.COPY_ACTION, 'abort'); var processResponseCallback = function (responseObject, next) { var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; // Internal Methods /** * Updates a file from text. * @ignore * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @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 {bool} [options.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @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, file, response)} callback `error` will contain information * if an error occurs; otherwise `file` will contain * the file information. * `response` will contain information related to this operation. */ FileService.prototype._createRanges = function (share, directory, file, text, readStream, rangeStart, rangeEnd, options, callback) { var request = this._updateFilesImpl(share, directory, file, rangeStart, rangeEnd, FileConstants.RangeWriteOptions.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. if(!azureutil.objectIsNull(text) && azureutil.objectIsNull(options.contentMD5) && options.useTransactionalMD5 === true) { request.withHeader(HeaderConstants.CONTENT_MD5, azureutil.getContentMd5(text)); } var processResponseCallback = function (responseObject, next) { responseObject.fileResult = null; if (!responseObject.error) { responseObject.fileResult = new FileResult(share, directory, file); responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.fileResult, returnObject.response); }; next(responseObject, finalCallback); }; if(!azureutil.objectIsNull(text)) { this.performRequest(request, text, options, processResponseCallback); } else { this.performRequestOutputStream(request, readStream, options, processResponseCallback); } }; /** * Uploads a file from a stream. * @ignore * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @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.useTransactionalMD5] Calculate and send/validate content MD5 for transactions. * @param {object} [options.metadata] The metadata key/value pairs. * @param {bool} [options.storeFileContentMD5] Specifies whether the file's ContentMD5 header should be set on uploads. * @param {string} [options.contentType] The MIME content type of the file. The default type is application/octet-stream. * @param {string} [options.contentEncoding] The content encodings that have been applied to the file. * @param {string} [options.contentLanguage] The natural languages used by this resource. * @param {string} [options.contentMD5] The MD5 hash of the file content. * @param {string} [options.cacheControl] The file service stores this value but does not use or modify it. * @param {string} [options.contentDisposition] The file's content disposition. * @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} */ FileService.prototype._createFileFromChunkStream = function(share, directory, file, chunkStream, streamLength, options, callback) { this.logger.debug(util.format('_createFileFromChunkStream for file %s', file)); var apiName = '_createRanges'; var sizeLimitation = FileConstants.DEFAULT_WRITE_SIZE_IN_BYTES; var originalContentMD5 = options.contentMD5; this._setOperationExpiryTime(options); // initialize the speed summary var speedSummary = options.speedSummary || new SpeedSummary(); speedSummary.totalSize = streamLength; var parallelOperationThreadCount = options.parallelOperationThreadCount || this.parallelOperationThreadCount; // initialize chunk allocator var allocator = new ChunkAllocator(sizeLimitation, options.parallelOperationThreadCount, { logger: this.logger }); // 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, { logger : this.logger }); batchOperations.setConcurrency(parallelOperationThreadCount); // initialize options var rangeOptions = { timeoutIntervalInMs: options.timeoutIntervalInMs, operationExpiryTime: options.operationExpiryTime }; 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; } if (azureutil.isBufferAllZero(data)) { self.logger.debug(util.format('Skip upload data from %s bytes to %s bytes to file %s', range.start, range.end, file)); speedSummary.increment(data.length); } else { operation = new BatchOperation.RestOperation(self, apiName, share, directory, file, data, null, range.start, range.end, rangeOptions, function (error) { if(!error) { autoIncrement(); } allocator.releaseBuffer(data); data = null; }); } 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 file %s', file)); 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'); if (error) { callback(error); return; } if (originalContentMD5) { options.contentMD5 = originalContentMD5; } else if (options.storeFileContentMD5) { options.contentMD5 = chunkStream.getContentMd5('base64'); } // upload file completely self.setFileProperties(share, directory, file, options, function (error, file, response) { chunkStream.finish(); callback(error, file, response); }); }); return speedSummary; }; /** * Downloads a file into a stream. * @ignore * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @param {Stream} writeStream The write stream. * @param {object} [options] The request options. * @param {string} [options.rangeStart] Return only the bytes of the file in the specified range. * @param {string} [options.rangeEnd] Return only the bytes of the file 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 files. * @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 file information. * `response` will contain information related to this operation. * * @return {SpeedSummary} */ FileService.prototype._getFileToStream = function (share, directory, file, writeStream, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('_getFileToStream', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.object(writeStream, 'writeStream'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(share, directory, file); var webResource = WebResource.get(resourceName).withRawResponse(); FileResult.setHeaders(webResource, options); this._setRangeContentMD5Header(webResource, options); var self = this; var processResponseCallback = function (responseObject, next) { responseObject.fileResult = null; if (!responseObject.error) { responseObject.fileResult = new FileResult(share, directory, file); responseObject.fileResult.metadata = self.parseMetadataHeaders(responseObject.response.headers); responseObject.fileResult.getPropertiesFromHeaders(responseObject.response.headers, true); self._validateLengthAndMD5(options, responseObject); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.fileResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequestInputStream(webResource, null, writeStream, options, processResponseCallback); }; /** * Downloads a file into a range stream. * @ignore * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @param {Stream} writeStream The write stream. * @param {object} [options] The request options. * @param {string} [options.rangeStart] Return only the bytes of the file in the specified range. * @param {string} [options.rangeEnd] Return only the bytes of the file 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 files. * @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 file information. * `response` will contain information related to this operation. * * @return {SpeedSummary} */ FileService.prototype._getFileToRangeStream = function (share, directory, file, writeStream, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('_getFileToRangeStream', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.object(writeStream, 'writeStream'); v.shareNameIsValid(share); v.callback(callback); }); var speedSummary = userOptions.speedSummary || new SpeedSummary(file); var parallelOperationThreadCount = userOptions.parallelOperationThreadCount || this.parallelOperationThreadCount; var batchOperations = new BatchOperation('getfile', { callbackInOrder: true, logger : this.logger }); batchOperations.setConcurrency(parallelOperationThreadCount); var rangeStream = new FileRangeStream(this, share, directory, file, userOptions); var self = this; var checkMD5sum = !userOptions.disableContentMD5Validation; var md5Hash = null; if (checkMD5sum) { md5Hash = crypto.createHash('md5'); } var savedFileResult = null; var savedFileResponse = 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 = userOptions.timeoutIntervalInMs; if (range.dataSize === 0) { 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); return; } if (range.start > range.end) { return; } var operation = new BatchOperation.RestOperation(self, 'getFileToText', share, directory, file, requestOptions, function (error, content, fileResult, 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 (!savedFileResult) { savedFileResult = fileResult; } if (!savedFileResponse) { savedFileResponse = 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); } else { writeStream.end(function () { self.logger.debug('Write stream has ended'); if (writeStream.close) { writeStream.close(); } if (!savedFileResult) { savedFileResult = {}; } savedFileResult.contentMD5 = userOptions.contentMD5; savedFileResult.clientSideContentMD5 = null; if (md5Hash) { savedFileResult.clientSideContentMD5 = md5Hash.digest('base64'); } callback(error, savedFileResult, savedFileResponse); }); } }); var listOptions = { timeoutIntervalInMs : userOptions.timeoutIntervalInMs, }; rangeStream.list(listOptions); return speedSummary; }; /** * @ignore */ FileService.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 > FileConstants.MAX_RANGE_GET_SIZE_WITH_MD5) { throw new Error(SR.INVALID_RANGE_FOR_MD5); } else { webResource.withHeader(HeaderConstants.RANGE_GET_CONTENT_MD5, 'true'); } } }; /** * @ignore */ FileService.prototype._updateFilesImpl = function (share, directory, file, rangeStart, rangeEnd, writeMethod, options) { var resourceName = createResourceName(share, directory, file); var webResource = WebResource.put(resourceName) .withQueryOption(QueryStringConstants.COMP, 'range') .withHeader(HeaderConstants.CONTENT_TYPE, 'application/octet-stream') .withHeader(HeaderConstants.FILE_WRITE, writeMethod); options.rangeStart = rangeStart; options.rangeEnd = rangeEnd; FileResult.setHeaders(webResource, options); if(writeMethod === FileConstants.RangeWriteOptions.UPDATE) { var size = (rangeEnd - rangeStart) + 1; webResource.withHeader(HeaderConstants.CONTENT_LENGTH, size); } else { webResource.withHeader(HeaderConstants.CONTENT_LENGTH, 0); } return webResource; }; /** * @ignore */ FileService.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 getFileToText 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; } }; /** * The callback for if exists methods. * @ignore * * @param {string} responseObject The object returned by the service. * @param {string} next The next function to call. */ function getExistsResponseCallback (callback) { var existsResponseCallback = 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); }; return existsResponseCallback; } /** * Checks whether or not a file exists on the service. * @ignore * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} file The file name. File names may not start or end with the delimiter '/'. * @param {string} primaryOnly If true, the request will be executed against the primary storage location. * @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 {Function(error, fileExists, response)} callback `error` will contain information * if an error occurs; otherwise `FileExists` will * be true if the file exists, or false if the file does not exist. * `response` will contain information related to this operation. */ FileService.prototype._doesFileExist = function (share, directory, file, primaryOnly, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('FileExists', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.string(file, 'file'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var resourceName = createResourceName(share, directory, file); var webResource = WebResource.head(resourceName); /*if(primaryOnly === false) { options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY; }*/ this.performRequest(webResource, null, options, getExistsResponseCallback(callback)); }; /** * Checks whether or not a directory exists on the service. * @ignore * * @this {FileService} * @param {string} share The share name. * @param {string} directory The directory name. Use '' to refer to the base directory. * @param {string} primaryOnly If true, the request will be executed against the primary storage location. * @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 {Function(error, directoryExists, response)} callback `error` will contain information * if an error occurs; otherwise `directoryExists` will contain * be true if the directory exists, or false if the directory does not exist. * `response` will contain information related to this operation. */ FileService.prototype._doesDirectoryExist = function (share, directory, primaryOnly, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('directoryExists', function (v) { v.string(share, 'share'); v.stringAllowEmpty(directory, 'directory'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.head(createResourceName(share, directory)) .withQueryOption(QueryStringConstants.RESTYPE, 'directory'); /*if(primaryOnly === false) { options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY; }*/ this.performRequest(webResource, null, options, getExistsResponseCallback(callback)); }; /** * Checks whether or not a share exists on the service. * @ignore * * @this {FileService} * @param {string} share The share name. * @param {string} primaryOnly If true, the request will be executed against the primary storage location. * @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 share exists and was deleted, or false if the share * did not exist. * `response` will contain information related to this operation. */ FileService.prototype._doesShareExist = function (share, primaryOnly, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('shareExists', function (v) { v.string(share, 'share'); v.shareNameIsValid(share); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.head(share) .withQueryOption(QueryStringConstants.RESTYPE, 'share'); /*if(primaryOnly === false) { options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY; }*/ this.performRequest(webResource, null, options, getExistsResponseCallback(callback)); }; /** * The callback for {FileService~getFileToText}. * @typedef {function} FileService~FileToText * @param {object} error If an error occurs, the error information. * @param {string} text The text returned from the file. * @param {object} file Information about the file. * @param {object} response Information related to this operation. */ FileService.SpeedSummary = SpeedSummary; module.exports = FileService;