Source for file Blob.php
Documentation is available at Blob.php
* Copyright (c) 2009 - 2011, RealDolmen
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of RealDolmen nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @package Microsoft_WindowsAzure
* @copyright Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
* @license http://todo name_todo
* @version $Id: Blob.php 61044 2011-04-19 10:21:34Z unknown $
* @see Microsoft_AutoLoader
require_once dirname(__FILE__ ) . '/../../AutoLoader.php';
* @package Microsoft_WindowsAzure
* @copyright Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
* @license http://phpazure.codeplex.com/license
* ACL - Public access (read all blobs)
* @deprecated Use ACL_PUBLIC_CONTAINER or ACL_PUBLIC_BLOB instead.
* ACL - Blob Public access (read all blobs)
* ACL - Container Public access (enumerate and read all blobs)
* Maximal blob size (in bytes)
* Maximal blob transfer size (in bytes)
protected static $_wrapperClients = array();
* SharedAccessSignature credentials
* @var Microsoft_WindowsAzure_Credentials_SharedAccessSignature
* Creates a new Microsoft_WindowsAzure_Storage_Blob instance
* @param string $host Storage host name
* @param string $accountName Account name for Windows Azure
* @param string $accountKey Account key for Windows Azure
* @param boolean $usePathStyleUri Use path-style URI's
* @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
public function __construct($host = Microsoft_WindowsAzure_Storage::URL_DEV_BLOB, $accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT, $accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY, $usePathStyleUri = false, Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
parent::__construct($host, $accountName, $accountKey, $usePathStyleUri, $retryPolicy);
// SharedAccessSignature credentials
* @param string $containerName Container name
* @param string $blobName Blob name
* @param string $snapshotId Snapshot identifier
public function blobExists($containerName = '', $blobName = '', $snapshotId = null)
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
* Check if a container exists
* @param string $containerName Container name
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
foreach ($containers as $container) {
if ($container->Name == $containerName) {
* @param string $containerName Container name
* @param array $metadata Key/value pairs of meta data
* @return object Container properties
* @throws Microsoft_WindowsAzure_Exception
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
// Create metadata headers
if ($response->isSuccessful()) {
$response->getHeader('Etag'),
$response->getHeader('Last-modified'),
* Create container if it does not exist
* @param string $containerName Container name
* @param array $metadata Key/value pairs of meta data
* @throws Microsoft_WindowsAzure_Exception
* @param string $containerName Container name
* @param bool $signedIdentifiers Display only private/blob/container or display signed identifiers?
* @return string Acl, to be compared with Microsoft_WindowsAzure_Storage_Blob::ACL_*
* @throws Microsoft_WindowsAzure_Exception
public function getContainerAcl($containerName = '', $signedIdentifiers = false)
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($response->isSuccessful()) {
if ($signedIdentifiers == false) {
// Only private/blob/container
$accessType = self::ACL_PUBLIC_CONTAINER;
if ($result->SignedIdentifier) {
if (count($result->SignedIdentifier) > 1) {
$entries = $result->SignedIdentifier;
$entries = array($result->SignedIdentifier);
foreach ($entries as $entry) {
$entry->AccessPolicy ? $entry->AccessPolicy->Start ? $entry->AccessPolicy->Start : '' : '',
$entry->AccessPolicy ? $entry->AccessPolicy->Expiry ? $entry->AccessPolicy->Expiry : '' : '',
$entry->AccessPolicy ? $entry->AccessPolicy->Permission ? $entry->AccessPolicy->Permission : '' : ''
* @param string $containerName Container name
* @param bool $acl Microsoft_WindowsAzure_Storage_Blob::ACL_*
* @param array $signedIdentifiers Signed identifiers
* @throws Microsoft_WindowsAzure_Exception
public function setContainerAcl($containerName = '', $acl = self::ACL_PRIVATE, $signedIdentifiers = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($acl != self::ACL_PRIVATE && !is_null($acl) && $acl != '') {
if (is_array($signedIdentifiers) && count($signedIdentifiers) > 0) {
$policies .= '<?xml version="1.0" encoding="utf-8"?>' . "\r\n";
$policies .= '<SignedIdentifiers>' . "\r\n";
foreach ($signedIdentifiers as $signedIdentifier) {
$policies .= ' <SignedIdentifier>' . "\r\n";
$policies .= ' <Id>' . $signedIdentifier->Id . '</Id>' . "\r\n";
$policies .= ' <AccessPolicy>' . "\r\n";
if ($signedIdentifier->Start != '')
$policies .= ' <Start>' . $signedIdentifier->Start . '</Start>' . "\r\n";
if ($signedIdentifier->Expiry != '')
$policies .= ' <Expiry>' . $signedIdentifier->Expiry . '</Expiry>' . "\r\n";
if ($signedIdentifier->Permissions != '')
$policies .= ' <Permission>' . $signedIdentifier->Permissions . '</Permission>' . "\r\n";
$policies .= ' </AccessPolicy>' . "\r\n";
$policies .= ' </SignedIdentifier>' . "\r\n";
$policies .= '</SignedIdentifiers>' . "\r\n";
if (!$response->isSuccessful()) {
* @param string $containerName Container name
* @return Microsoft_WindowsAzure_Storage_BlobContainer
* @throws Microsoft_WindowsAzure_Exception
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($response->isSuccessful()) {
$response->getHeader('Etag'),
$response->getHeader('Last-modified'),
* @param string $containerName Container name
* @return array Key/value pairs of meta data
* @throws Microsoft_WindowsAzure_Exception
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
* Calling the Set Container Metadata operation overwrites all existing metadata that is associated with the container. It's not possible to modify an individual name/value pair.
* @param string $containerName Container name
* @param array $metadata Key/value pairs of meta data
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
* @throws Microsoft_WindowsAzure_Exception
public function setContainerMetadata($containerName = '', $metadata = array(), $additionalHeaders = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if (count($metadata) == 0) {
// Create metadata headers
foreach ($additionalHeaders as $key => $value) {
if (!$response->isSuccessful()) {
* @param string $containerName Container name
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
* @throws Microsoft_WindowsAzure_Exception
public function deleteContainer($containerName = '', $additionalHeaders = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
foreach ($additionalHeaders as $key => $value) {
if (!$response->isSuccessful()) {
* @param string $prefix Optional. Filters the results to return only containers whose name begins with the specified prefix.
* @param int $maxResults Optional. Specifies the maximum number of containers to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000)
* @param string $marker Optional string value that identifies the portion of the list to be returned with the next list operation.
* @param string $include Optional. Include this parameter to specify that the container's metadata be returned as part of the response body. (allowed values: '', 'metadata')
* @param int $currentResultCount Current result count (internal use)
* @throws Microsoft_WindowsAzure_Exception
public function listContainers($prefix = null, $maxResults = null, $marker = null, $include = null, $currentResultCount = 0)
$queryString = array('comp=list');
$queryString[] = 'prefix=' . $prefix;
$queryString[] = 'maxresults=' . $maxResults;
$queryString[] = 'marker=' . $marker;
$queryString[] = 'include=' . $include;
$queryString = self::createQueryStringFromArray($queryString);
if ($response->isSuccessful()) {
$xmlContainers = $this->_parseResponse($response)->Containers->Container;
for ($i = 0; $i < count($xmlContainers); $i++ ) {
(string) $xmlContainers[$i]->Name,
(string) $xmlContainers[$i]->Etag,
(string) $xmlContainers[$i]->LastModified,
$currentResultCount = $currentResultCount + count($containers);
if (!is_null($maxResults) && $currentResultCount < $maxResults) {
if (!is_null($xmlMarker) && $xmlMarker != '') {
$containers = array_merge($containers, $this->listContainers($prefix, $maxResults, $xmlMarker, $include, $currentResultCount));
if (!is_null($maxResults) && count($containers) > $maxResults) {
$containers = array_slice($containers, 0, $maxResults);
* @param string $containerName Container name
* @param string $blobName Blob name
* @param string $localFileName Local file name to be uploaded
* @param array $metadata Key/value pairs of meta data
* @param string $leaseId Lease identifier
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
* @return object Partial blob properties
* @throws Microsoft_WindowsAzure_Exception
public function putBlob($containerName = '', $blobName = '', $localFileName = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($localFileName === '') {
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
if (filesize($localFileName) >= self::MAX_BLOB_SIZE) {
return $this->putLargeBlob($containerName, $blobName, $localFileName, $metadata, $leaseId, $additionalHeaders);
// Put the data to Windows Azure Storage
* @param string $containerName Container name
* @param string $blobName Blob name
* @param mixed $data Data to store
* @param array $metadata Key/value pairs of meta data
* @param string $leaseId Lease identifier
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
* @return object Partial blob properties
* @throws Microsoft_WindowsAzure_Exception
public function putBlobData($containerName = '', $blobName = '', $data = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
// Create metadata headers
$headers['x-ms-lease-id'] = $leaseId;
foreach ($additionalHeaders as $key => $value) {
$resourceName = self::createResourceName($containerName , $blobName);
if ($response->isSuccessful()) {
$response->getHeader('Etag'),
$response->getHeader('Last-modified'),
$this->getBaseUrl() . '/' . $containerName . '/' . $blobName,
* Put large blob (> 64 MB)
* @param string $containerName Container name
* @param string $blobName Blob name
* @param string $localFileName Local file name to be uploaded
* @param array $metadata Key/value pairs of meta data
* @param string $leaseId Lease identifier
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
* @return object Partial blob properties
* @throws Microsoft_WindowsAzure_Exception
public function putLargeBlob($containerName = '', $blobName = '', $localFileName = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($localFileName === '') {
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
if (filesize($localFileName) < self::MAX_BLOB_SIZE) {
return $this->putBlob($containerName, $blobName, $localFileName, $metadata, $leaseId, $additionalHeaders);
// Determine number of parts
$numberOfParts = ceil( filesize($localFileName) / self::MAX_BLOB_TRANSFER_SIZE );
$blockIdentifiers = array();
for ($i = 0; $i < $numberOfParts; $i++ ) {
$fp = fopen($localFileName, 'r');
for ($i = 0; $i < $numberOfParts; $i++ ) {
fseek($fp, $i * self::MAX_BLOB_TRANSFER_SIZE);
$fileContents = fread($fp, self::MAX_BLOB_TRANSFER_SIZE);
$this->putBlock($containerName, $blobName, $blockIdentifiers[$i], $fileContents, $leaseId);
$this->putBlockList($containerName, $blobName, $blockIdentifiers, $metadata, $leaseId, $additionalHeaders);
// Return information of the blob
* @param string $containerName Container name
* @param string $blobName Blob name
* @param string $identifier Block ID
* @param array $contents Contents of the block
* @param string $leaseId Lease identifier
* @throws Microsoft_WindowsAzure_Exception
public function putBlock($containerName = '', $blobName = '', $identifier = '', $contents = '', $leaseId = null)
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($identifier === '') {
if (strlen($contents) > self::MAX_BLOB_TRANSFER_SIZE) {
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
$headers['x-ms-lease-id'] = $leaseId;
$resourceName = self::createResourceName($containerName , $blobName);
if (!$response->isSuccessful()) {
* @param string $containerName Container name
* @param string $blobName Blob name
* @param array $blockList Array of block identifiers
* @param array $metadata Key/value pairs of meta data
* @param string $leaseId Lease identifier
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
* @throws Microsoft_WindowsAzure_Exception
public function putBlockList($containerName = '', $blobName = '', $blockList = array(), $metadata = array(), $leaseId = null, $additionalHeaders = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if (count($blockList) == 0) {
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
foreach ($blockList as $block) {
$blocks .= ' <Latest>' . base64_encode($block) . '</Latest>' . "\n";
// Generate block list request
'<?xml version="1.0" encoding="utf-8"?>',
// Create metadata headers
$headers['x-ms-lease-id'] = $leaseId;
foreach ($additionalHeaders as $key => $value) {
$resourceName = self::createResourceName($containerName , $blobName);
if (!$response->isSuccessful()) {
* @param string $containerName Container name
* @param string $blobName Blob name
* @param string $snapshotId Snapshot identifier
* @param string $leaseId Lease identifier
* @param integer $type Type of block list to retrieve. 0 = all, 1 = committed, 2 = uncommitted
* @throws Microsoft_WindowsAzure_Exception
public function getBlockList($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null, $type = 0)
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($type < 0 || $type > 2) {
$blockListType = 'committed';
$blockListType = 'uncommitted';
$headers['x-ms-lease-id'] = $leaseId;
$queryString = array('comp=blocklist', 'blocklisttype=' . $blockListType);
$queryString[] = 'snapshot=' . $snapshotId;
$queryString = self::createQueryStringFromArray($queryString);
$resourceName = self::createResourceName($containerName , $blobName);
if ($response->isSuccessful()) {
if ($blockList->CommittedBlocks) {
foreach ($blockList->CommittedBlocks->Block as $block) {
$returnValue['CommittedBlocks'][] = (object) array(
'Name' => (string) $block->Name,
'Size' => (string) $block->Size
if ($blockList->UncommittedBlocks) {
foreach ($blockList->UncommittedBlocks->Block as $block) {
$returnValue['UncommittedBlocks'][] = (object) array(
'Name' => (string) $block->Name,
'Size' => (string) $block->Size
* @param string $containerName Container name
* @param string $blobName Blob name
* @param int $size Size of the page blob in bytes
* @param array $metadata Key/value pairs of meta data
* @param string $leaseId Lease identifier
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
* @return object Partial blob properties
* @throws Microsoft_WindowsAzure_Exception
public function createPageBlob($containerName = '', $blobName = '', $size = 0, $metadata = array(), $leaseId = null, $additionalHeaders = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
// Create metadata headers
$headers['x-ms-lease-id'] = $leaseId;
foreach ($additionalHeaders as $key => $value) {
// Specify blob type & blob length
$headers['Content-Length'] = 0;
$resourceName = self::createResourceName($containerName , $blobName);
if ($response->isSuccessful()) {
$response->getHeader('Etag'),
$response->getHeader('Last-modified'),
$this->getBaseUrl() . '/' . $containerName . '/' . $blobName,
* @param string $containerName Container name
* @param string $blobName Blob name
* @param int $startByteOffset Start byte offset
* @param int $endByteOffset End byte offset
* @param mixed $contents Page contents
* @param string $writeMethod Write method (Microsoft_WindowsAzure_Storage_Blob::PAGE_WRITE_*)
* @param string $leaseId Lease identifier
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
* @throws Microsoft_WindowsAzure_Exception
public function putPage($containerName = '', $blobName = '', $startByteOffset = 0, $endByteOffset = 0, $contents = '', $writeMethod = self::PAGE_WRITE_UPDATE, $leaseId = null, $additionalHeaders = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
if ($startByteOffset % 512 != 0) {
if (($endByteOffset + 1) % 512 != 0) {
if ($size >= self::MAX_BLOB_TRANSFER_SIZE) {
// Create metadata headers
$headers['x-ms-lease-id'] = $leaseId;
foreach ($additionalHeaders as $key => $value) {
$headers['Range'] = 'bytes=' . $startByteOffset . '-' . $endByteOffset;
$resourceName = self::createResourceName($containerName , $blobName);
if (!$response->isSuccessful()) {
* @param string $containerName Container name
* @param string $blobName Blob name
* @param int $startByteOffset Start byte offset
* @param int $endByteOffset End byte offset
* @param string $leaseId Lease identifier
* @return array Array of page ranges
* @throws Microsoft_WindowsAzure_Exception
public function getPageRegions($containerName = '', $blobName = '', $startByteOffset = 0, $endByteOffset = 0, $leaseId = null)
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
if ($startByteOffset % 512 != 0) {
if ($endByteOffset > 0 && ($endByteOffset + 1) % 512 != 0) {
// Create metadata headers
$headers['x-ms-lease-id'] = $leaseId;
if ($endByteOffset > 0) {
$headers['Range'] = 'bytes=' . $startByteOffset . '-' . $endByteOffset;
$resourceName = self::createResourceName($containerName , $blobName);
if ($response->isSuccessful()) {
if (count($result->PageRange) > 1) {
$xmlRanges = $result->PageRange;
$xmlRanges = array($result->PageRange);
for ($i = 0; $i < count($xmlRanges); $i++ ) {
(int) $xmlRanges[$i]->Start,
* @param string $sourceContainerName Source container name
* @param string $sourceBlobName Source blob name
* @param string $destinationContainerName Destination container name
* @param string $destinationBlobName Destination blob name
* @param array $metadata Key/value pairs of meta data
* @param string $sourceSnapshotId Source snapshot identifier
* @param string $destinationLeaseId Destination lease identifier
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd894037.aspx for more information.
* @return object Partial blob properties
* @throws Microsoft_WindowsAzure_Exception
public function copyBlob($sourceContainerName = '', $sourceBlobName = '', $destinationContainerName = '', $destinationBlobName = '', $metadata = array(), $sourceSnapshotId = null, $destinationLeaseId = null, $additionalHeaders = array())
if ($sourceContainerName === '') {
if (!self::isValidContainerName($sourceContainerName)) {
throw new Microsoft_WindowsAzure_Exception('Source container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($sourceBlobName === '') {
if ($destinationContainerName === '') {
if (!self::isValidContainerName($destinationContainerName)) {
throw new Microsoft_WindowsAzure_Exception('Destination container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($destinationBlobName === '') {
if ($sourceContainerName === '$root' && strpos($sourceBlobName, '/') !== false) {
if ($destinationContainerName === '$root' && strpos($destinationBlobName, '/') !== false) {
// Create metadata headers
if (!is_null($destinationLeaseId)) {
$headers['x-ms-lease-id'] = $destinationLeaseId;
foreach ($additionalHeaders as $key => $value) {
$sourceResourceName = self::createResourceName($sourceContainerName, $sourceBlobName);
$sourceResourceName .= '?snapshot=' . $sourceSnapshotId;
$destinationResourceName = self::createResourceName($destinationContainerName, $destinationBlobName);
$headers["x-ms-copy-source"] = '/' . $this->_accountName . '/' . $sourceResourceName;
if ($response->isSuccessful()) {
$destinationContainerName,
$response->getHeader('Etag'),
$response->getHeader('Last-modified'),
$this->getBaseUrl() . '/' . $destinationContainerName . '/' . $destinationBlobName,
* @param string $containerName Container name
* @param string $blobName Blob name
* @param string $localFileName Local file name to store downloaded blob
* @param string $snapshotId Snapshot identifier
* @param string $leaseId Lease identifier
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
* @throws Microsoft_WindowsAzure_Exception
public function getBlob($containerName = '', $blobName = '', $localFileName = '', $snapshotId = null, $leaseId = null, $additionalHeaders = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($localFileName === '') {
* @param string $containerName Container name
* @param string $blobName Blob name
* @param string $snapshotId Snapshot identifier
* @param string $leaseId Lease identifier
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
* @return mixed Blob contents
* @throws Microsoft_WindowsAzure_Exception
public function getBlobData($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null, $additionalHeaders = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
$queryString[] = 'snapshot=' . $snapshotId;
$queryString = self::createQueryStringFromArray($queryString);
$headers['x-ms-lease-id'] = $leaseId;
foreach ($additionalHeaders as $key => $value) {
$resourceName = self::createResourceName($containerName , $blobName);
if ($response->isSuccessful()) {
return $response->getBody();
* @param string $containerName Container name
* @param string $blobName Blob name
* @param string $snapshotId Snapshot identifier
* @param string $leaseId Lease identifier
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
* @return Microsoft_WindowsAzure_Storage_BlobInstance
* @throws Microsoft_WindowsAzure_Exception
public function getBlobInstance($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null, $additionalHeaders = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
$queryString[] = 'snapshot=' . $snapshotId;
$queryString = self::createQueryStringFromArray($queryString);
$headers['x-ms-lease-id'] = $leaseId;
foreach ($additionalHeaders as $key => $value) {
$resourceName = self::createResourceName($containerName , $blobName);
if ($response->isSuccessful()) {
$response->getHeader('Etag'),
$response->getHeader('Last-modified'),
$this->getBaseUrl() . '/' . $containerName . '/' . $blobName,
$response->getHeader('Content-Length'),
$response->getHeader('Content-Type'),
$response->getHeader('Content-Encoding'),
$response->getHeader('Content-Language'),
$response->getHeader('Cache-Control'),
$response->getHeader('x-ms-blob-type'),
$response->getHeader('x-ms-lease-status'),
* @param string $containerName Container name
* @param string $blobName Blob name
* @param string $snapshotId Snapshot identifier
* @param string $leaseId Lease identifier
* @return array Key/value pairs of meta data
* @throws Microsoft_WindowsAzure_Exception
public function getBlobMetadata($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null)
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
return $this->getBlobInstance($containerName, $blobName, $snapshotId, $leaseId)->Metadata;
* Calling the Set Blob Metadata operation overwrites all existing metadata that is associated with the blob. It's not possible to modify an individual name/value pair.
* @param string $containerName Container name
* @param string $blobName Blob name
* @param array $metadata Key/value pairs of meta data
* @param string $leaseId Lease identifier
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
* @throws Microsoft_WindowsAzure_Exception
public function setBlobMetadata($containerName = '', $blobName = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
if (count($metadata) == 0) {
// Create metadata headers
$headers['x-ms-lease-id'] = $leaseId;
foreach ($additionalHeaders as $key => $value) {
if (!$response->isSuccessful()) {
* All available properties are listed at http://msdn.microsoft.com/en-us/library/ee691966.aspx and should be provided in the $additionalHeaders parameter.
* @param string $containerName Container name
* @param string $blobName Blob name
* @param string $leaseId Lease identifier
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
* @throws Microsoft_WindowsAzure_Exception
public function setBlobProperties($containerName = '', $blobName = '', $leaseId = null, $additionalHeaders = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
if (count($additionalHeaders) == 0) {
$headers['x-ms-lease-id'] = $leaseId;
foreach ($additionalHeaders as $key => $value) {
if (!$response->isSuccessful()) {
* @param string $containerName Container name
* @param string $blobName Blob name
* @param string $snapshotId Snapshot identifier
* @param string $leaseId Lease identifier
* @return Microsoft_WindowsAzure_Storage_BlobInstance
* @throws Microsoft_WindowsAzure_Exception
public function getBlobProperties($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null)
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
return $this->getBlobInstance($containerName, $blobName, $snapshotId, $leaseId);
* @param string $containerName Container name
* @param string $blobName Blob name
* @param string $snapshotId Snapshot identifier
* @param string $leaseId Lease identifier
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
* @throws Microsoft_WindowsAzure_Exception
public function deleteBlob($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null, $additionalHeaders = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
$queryString[] = 'snapshot=' . $snapshotId;
$queryString = self::createQueryStringFromArray($queryString);
$headers['x-ms-lease-id'] = $leaseId;
foreach ($additionalHeaders as $key => $value) {
$resourceName = self::createResourceName($containerName , $blobName);
if (!$response->isSuccessful()) {
* @param string $containerName Container name
* @param string $blobName Blob name
* @param array $metadata Key/value pairs of meta data
* @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
* @return string Date/Time value representing the snapshot identifier.
* @throws Microsoft_WindowsAzure_Exception
public function snapshotBlob($containerName = '', $blobName = '', $metadata = array(), $additionalHeaders = array())
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
foreach ($additionalHeaders as $key => $value) {
$resourceName = self::createResourceName($containerName , $blobName);
if ($response->isSuccessful()) {
return $response->getHeader('x-ms-snapshot');
* Lease blob - See (http://msdn.microsoft.com/en-us/library/ee691972.aspx)
* @param string $containerName Container name
* @param string $blobName Blob name
* @param string $leaseAction Lease action (Microsoft_WindowsAzure_Storage_Blob::LEASE_*)
* @param string $leaseId Lease identifier, required to renew the lease or to release the lease.
* @return Microsoft_WindowsAzure_Storage_LeaseInstance Lease instance
* @throws Microsoft_WindowsAzure_Exception
public function leaseBlob($containerName = '', $blobName = '', $leaseAction = self::LEASE_ACQUIRE, $leaseId = null)
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
if ($containerName === '$root' && strpos($blobName, '/') !== false) {
$headers['x-ms-lease-action'] = strtolower($leaseAction);
$headers['x-ms-lease-id'] = $leaseId;
$resourceName = self::createResourceName($containerName , $blobName);
if ($response->isSuccessful()) {
$response->getHeader('x-ms-lease-id'),
$response->getHeader('x-ms-lease-time'));
* @param string $containerName Container name
* @param string $prefix Optional. Filters the results to return only blobs whose name begins with the specified prefix.
* @param string $delimiter Optional. Delimiter, i.e. '/', for specifying folder hierarchy
* @param int $maxResults Optional. Specifies the maximum number of blobs to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000)
* @param string $marker Optional string value that identifies the portion of the list to be returned with the next list operation.
* @param string $include Optional. Specifies that the response should include one or more of the following subsets: '', 'metadata', 'snapshots', 'uncommittedblobs'). Multiple values can be added separated with a comma (,)
* @param int $currentResultCount Current result count (internal use)
* @throws Microsoft_WindowsAzure_Exception
public function listBlobs($containerName = '', $prefix = '', $delimiter = '', $maxResults = null, $marker = null, $include = null, $currentResultCount = 0)
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
$queryString = array('restype=container', 'comp=list');
$queryString[] = 'prefix=' . $prefix;
$queryString[] = 'delimiter=' . $delimiter;
$queryString[] = 'maxresults=' . $maxResults;
$queryString[] = 'marker=' . $marker;
$queryString[] = 'include=' . $include;
$queryString = self::createQueryStringFromArray($queryString);
if ($response->isSuccessful()) {
for ($i = 0; $i < count($xmlBlobs); $i++ ) {
$properties = (array) $xmlBlobs[$i]->Properties;
(string) $xmlBlobs[$i]->Name,
(string) $xmlBlobs[$i]->Snapshot,
(string) $properties['Etag'],
(string) $properties['Last-Modified'],
(string) $xmlBlobs[$i]->Url,
(string) $properties['Content-Length'],
(string) $properties['Content-Type'],
(string) $properties['Content-Encoding'],
(string) $properties['Content-Language'],
(string) $properties['Cache-Control'],
(string) $properties['BlobType'],
(string) $properties['LeaseStatus'],
// Blob prefixes (folders)
for ($i = 0; $i < count($xmlBlobs); $i++ ) {
(string) $xmlBlobs[$i]->Name,
$currentResultCount = $currentResultCount + count($blobs);
if (!is_null($maxResults) && $currentResultCount < $maxResults) {
if (!is_null($xmlMarker) && $xmlMarker != '') {
$blobs = array_merge($blobs, $this->listBlobs($containerName, $prefix, $delimiter, $maxResults, $marker, $include, $currentResultCount));
* Generate shared access URL
* @param string $containerName Container name
* @param string $blobName Blob name
* @param string $resource Signed resource - container (c) - blob (b)
* @param string $permissions Signed permissions - read (r), write (w), delete (d) and list (l)
* @param string $start The time at which the Shared Access Signature becomes valid.
* @param string $expiry The time at which the Shared Access Signature becomes invalid.
* @param string $identifier Signed identifier
public function generateSharedAccessUrl($containerName = '', $blobName = '', $resource = 'b', $permissions = 'r', $start = '', $expiry = '', $identifier = '')
if ($containerName === '') {
if (!self::isValidContainerName($containerName)) {
throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
$resourceName = self::createResourceName($containerName , $blobName);
return $this->getBaseUrl() . '/' . $resourceName . '?' .
* Register this object as stream wrapper client
* @param string $name Protocol name
* @return Microsoft_WindowsAzure_Storage_Blob
self::$_wrapperClients[$name] = $this;
* Unregister this object as stream wrapper client
* @param string $name Protocol name
* @return Microsoft_WindowsAzure_Storage_Blob
unset (self::$_wrapperClients[$name]);
* Get wrapper client for stream type
* @param string $name Protocol name
* @return Microsoft_WindowsAzure_Storage_Blob
return self::$_wrapperClients[$name];
* Register this object as stream wrapper
* @param string $name Protocol name
* @see Microsoft_WindowsAzure_Storage_Blob_Stream
require_once 'Microsoft/WindowsAzure/Storage/Blob/Stream.php';
stream_register_wrapper($name, 'Microsoft_WindowsAzure_Storage_Blob_Stream');
* Unregister this object as stream wrapper
* @param string $name Protocol name
* @return Microsoft_WindowsAzure_Storage_Blob
* @param string $containerName Container name
* @param string $blobName Blob name
$resourceName = $containerName . '/' . $blobName;
if ($containerName === '' || $containerName === '$root') {
$resourceName = $blobName;
$resourceName = $containerName;
* Is valid container name?
* @param string $containerName Container name
if ($containerName == '$root') {
if (preg_match("/^[a-z0-9][a-z0-9-]*$/", $containerName) === 0) {
if (strpos($containerName, '--') !== false) {
if (strtolower($containerName) != $containerName) {
if (strlen($containerName) < 3 || strlen($containerName) > 63) {
if (substr($containerName, - 1) == '-') {
* Get error message from Microsoft_Http_Response
* @param Microsoft_Http_Response $response Repsonse
* @param string $alternativeError Alternative error message
protected function _getErrorMessage(Microsoft_Http_Response $response, $alternativeError = 'Unknown error.')
if ($response && $response->Message) {
return (string) $response->Message;
return $alternativeError;
* @param int $part Block number
* @return string Windows Azure Blob Storage block number
while (strlen($returnValue) < 64) {
$returnValue = '0' . $returnValue;
|