PageRenderTime 72ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/Service/WindowsAzure/Storage/Blob.php

https://bitbucket.org/jfrubiom/zendframework-1.x
PHP | 2139 lines | 1333 code | 204 blank | 602 comment | 293 complexity | 87e79deacef9b5d43dab495571b31b04 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Service_WindowsAzure
  17. * @subpackage Storage
  18. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://todo name_todo
  20. * @version $Id: Blob.php 24593 2012-01-05 20:35:02Z matthew $
  21. */
  22. /**
  23. * @see Zend_Service_WindowsAzure_Storage
  24. */
  25. require_once 'Zend/Service/WindowsAzure/Storage.php';
  26. /**
  27. * @see Zend_Service_WindowsAzure_Storage_BlobInstance
  28. */
  29. require_once 'Zend/Service/WindowsAzure/Storage/BlobInstance.php';
  30. /**
  31. * @see Zend_Service_WindowsAzure_Storage_BlobContainer
  32. */
  33. require_once 'Zend/Service/WindowsAzure/Storage/BlobContainer.php';
  34. /**
  35. * @see Zend_Service_WindowsAzure_Storage_PageRegionInstance
  36. */
  37. require_once 'Zend/Service/WindowsAzure/Storage/PageRegionInstance.php';
  38. /**
  39. * @see Zend_Service_WindowsAzure_Storage_LeaseInstance
  40. */
  41. require_once 'Zend/Service/WindowsAzure/Storage/LeaseInstance.php';
  42. /**
  43. * @see Zend_Service_WindowsAzure_Storage_Blob_Stream
  44. */
  45. require_once 'Zend/Service/WindowsAzure/Storage/Blob/Stream.php';
  46. /**
  47. * @category Zend
  48. * @package Zend_Service_WindowsAzure
  49. * @subpackage Storage
  50. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  51. * @license http://framework.zend.com/license/new-bsd New BSD License
  52. */
  53. class Zend_Service_WindowsAzure_Storage_Blob extends Zend_Service_WindowsAzure_Storage
  54. {
  55. /**
  56. * ACL - Private access
  57. */
  58. const ACL_PRIVATE = null;
  59. /**
  60. * ACL - Public access (read all blobs)
  61. *
  62. * @deprecated Use ACL_PUBLIC_CONTAINER or ACL_PUBLIC_BLOB instead.
  63. */
  64. const ACL_PUBLIC = 'container';
  65. /**
  66. * ACL - Blob Public access (read all blobs)
  67. */
  68. const ACL_PUBLIC_BLOB = 'blob';
  69. /**
  70. * ACL - Container Public access (enumerate and read all blobs)
  71. */
  72. const ACL_PUBLIC_CONTAINER = 'container';
  73. /**
  74. * Blob lease constants
  75. */
  76. const LEASE_ACQUIRE = 'acquire';
  77. const LEASE_RENEW = 'renew';
  78. const LEASE_RELEASE = 'release';
  79. const LEASE_BREAK = 'break';
  80. /**
  81. * Maximal blob size (in bytes)
  82. */
  83. const MAX_BLOB_SIZE = 67108864;
  84. /**
  85. * Maximal blob transfer size (in bytes)
  86. */
  87. const MAX_BLOB_TRANSFER_SIZE = 4194304;
  88. /**
  89. * Blob types
  90. */
  91. const BLOBTYPE_BLOCK = 'BlockBlob';
  92. const BLOBTYPE_PAGE = 'PageBlob';
  93. /**
  94. * Put page write options
  95. */
  96. const PAGE_WRITE_UPDATE = 'update';
  97. const PAGE_WRITE_CLEAR = 'clear';
  98. /**
  99. * Stream wrapper clients
  100. *
  101. * @var array
  102. */
  103. protected static $_wrapperClients = array();
  104. /**
  105. * SharedAccessSignature credentials
  106. *
  107. * @var Zend_Service_WindowsAzure_Credentials_SharedAccessSignature
  108. */
  109. protected $_sharedAccessSignatureCredentials = null;
  110. /**
  111. * Creates a new Zend_Service_WindowsAzure_Storage_Blob instance
  112. *
  113. * @param string $host Storage host name
  114. * @param string $accountName Account name for Windows Azure
  115. * @param string $accountKey Account key for Windows Azure
  116. * @param boolean $usePathStyleUri Use path-style URI's
  117. * @param Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
  118. */
  119. public function __construct($host = Zend_Service_WindowsAzure_Storage::URL_DEV_BLOB, $accountName = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT, $accountKey = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY, $usePathStyleUri = false, Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
  120. {
  121. parent::__construct($host, $accountName, $accountKey, $usePathStyleUri, $retryPolicy);
  122. // API version
  123. $this->_apiVersion = '2009-09-19';
  124. // SharedAccessSignature credentials
  125. $this->_sharedAccessSignatureCredentials = new Zend_Service_WindowsAzure_Credentials_SharedAccessSignature($accountName, $accountKey, $usePathStyleUri);
  126. }
  127. /**
  128. * Check if a blob exists
  129. *
  130. * @param string $containerName Container name
  131. * @param string $blobName Blob name
  132. * @param string $snapshotId Snapshot identifier
  133. * @return boolean
  134. */
  135. public function blobExists($containerName = '', $blobName = '', $snapshotId = null)
  136. {
  137. if ($containerName === '') {
  138. require_once 'Zend/Service/WindowsAzure/Exception.php';
  139. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  140. }
  141. if (!self::isValidContainerName($containerName)) {
  142. require_once 'Zend/Service/WindowsAzure/Exception.php';
  143. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  144. }
  145. if ($blobName === '') {
  146. require_once 'Zend/Service/WindowsAzure/Exception.php';
  147. throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.');
  148. }
  149. // Get blob instance
  150. try {
  151. $this->getBlobInstance($containerName, $blobName, $snapshotId);
  152. } catch (Zend_Service_WindowsAzure_Exception $e) {
  153. return false;
  154. }
  155. return true;
  156. }
  157. /**
  158. * Check if a container exists
  159. *
  160. * @param string $containerName Container name
  161. * @return boolean
  162. */
  163. public function containerExists($containerName = '')
  164. {
  165. if ($containerName === '') {
  166. require_once 'Zend/Service/WindowsAzure/Exception.php';
  167. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  168. }
  169. if (!self::isValidContainerName($containerName)) {
  170. require_once 'Zend/Service/WindowsAzure/Exception.php';
  171. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  172. }
  173. // List containers
  174. $containers = $this->listContainers($containerName, 1);
  175. foreach ($containers as $container) {
  176. if ($container->Name == $containerName) {
  177. return true;
  178. }
  179. }
  180. return false;
  181. }
  182. /**
  183. * Create container
  184. *
  185. * @param string $containerName Container name
  186. * @param array $metadata Key/value pairs of meta data
  187. * @return object Container properties
  188. * @throws Zend_Service_WindowsAzure_Exception
  189. */
  190. public function createContainer($containerName = '', $metadata = array())
  191. {
  192. if ($containerName === '') {
  193. require_once 'Zend/Service/WindowsAzure/Exception.php';
  194. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  195. }
  196. if (!self::isValidContainerName($containerName)) {
  197. require_once 'Zend/Service/WindowsAzure/Exception.php';
  198. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  199. }
  200. if (!is_array($metadata)) {
  201. require_once 'Zend/Service/WindowsAzure/Exception.php';
  202. throw new Zend_Service_WindowsAzure_Exception('Meta data should be an array of key and value pairs.');
  203. }
  204. // Create metadata headers
  205. $headers = array();
  206. $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
  207. // Perform request
  208. $response = $this->_performRequest($containerName, '?restype=container', Zend_Http_Client::PUT, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  209. if ($response->isSuccessful()) {
  210. return new Zend_Service_WindowsAzure_Storage_BlobContainer(
  211. $containerName,
  212. $response->getHeader('Etag'),
  213. $response->getHeader('Last-modified'),
  214. $metadata
  215. );
  216. } else {
  217. require_once 'Zend/Service/WindowsAzure/Exception.php';
  218. throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  219. }
  220. }
  221. /**
  222. * Create container if it does not exist
  223. *
  224. * @param string $containerName Container name
  225. * @param array $metadata Key/value pairs of meta data
  226. * @throws Zend_Service_WindowsAzure_Exception
  227. */
  228. public function createContainerIfNotExists($containerName = '', $metadata = array())
  229. {
  230. if (!$this->containerExists($containerName)) {
  231. $this->createContainer($containerName, $metadata);
  232. }
  233. }
  234. /**
  235. * Get container ACL
  236. *
  237. * @param string $containerName Container name
  238. * @param bool $signedIdentifiers Display only private/blob/container or display signed identifiers?
  239. * @return string Acl, to be compared with Zend_Service_WindowsAzure_Storage_Blob::ACL_*
  240. * @throws Zend_Service_WindowsAzure_Exception
  241. */
  242. public function getContainerAcl($containerName = '', $signedIdentifiers = false)
  243. {
  244. if ($containerName === '') {
  245. require_once 'Zend/Service/WindowsAzure/Exception.php';
  246. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  247. }
  248. if (!self::isValidContainerName($containerName)) {
  249. require_once 'Zend/Service/WindowsAzure/Exception.php';
  250. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  251. }
  252. // Perform request
  253. $response = $this->_performRequest($containerName, '?restype=container&comp=acl', Zend_Http_Client::GET, array(), false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
  254. if ($response->isSuccessful()) {
  255. if ($signedIdentifiers == false) {
  256. // Only private/blob/container
  257. $accessType = $response->getHeader(Zend_Service_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-public-access');
  258. if (strtolower($accessType) == 'true') {
  259. $accessType = self::ACL_PUBLIC_CONTAINER;
  260. }
  261. return $accessType;
  262. } else {
  263. // Parse result
  264. $result = $this->_parseResponse($response);
  265. if (!$result) {
  266. return array();
  267. }
  268. $entries = null;
  269. if ($result->SignedIdentifier) {
  270. if (count($result->SignedIdentifier) > 1) {
  271. $entries = $result->SignedIdentifier;
  272. } else {
  273. $entries = array($result->SignedIdentifier);
  274. }
  275. }
  276. require_once 'Zend/Service/WindowsAzure/Storage/SignedIdentifier.php';
  277. // Return value
  278. $returnValue = array();
  279. foreach ($entries as $entry) {
  280. $returnValue[] = new Zend_Service_WindowsAzure_Storage_SignedIdentifier(
  281. $entry->Id,
  282. $entry->AccessPolicy ? $entry->AccessPolicy->Start ? $entry->AccessPolicy->Start : '' : '',
  283. $entry->AccessPolicy ? $entry->AccessPolicy->Expiry ? $entry->AccessPolicy->Expiry : '' : '',
  284. $entry->AccessPolicy ? $entry->AccessPolicy->Permission ? $entry->AccessPolicy->Permission : '' : ''
  285. );
  286. }
  287. // Return
  288. return $returnValue;
  289. }
  290. } else {
  291. require_once 'Zend/Service/WindowsAzure/Exception.php';
  292. throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  293. }
  294. }
  295. /**
  296. * Set container ACL
  297. *
  298. * @param string $containerName Container name
  299. * @param bool $acl Zend_Service_WindowsAzure_Storage_Blob::ACL_*
  300. * @param array $signedIdentifiers Signed identifiers
  301. * @throws Zend_Service_WindowsAzure_Exception
  302. */
  303. public function setContainerAcl($containerName = '', $acl = self::ACL_PRIVATE, $signedIdentifiers = array())
  304. {
  305. if ($containerName === '') {
  306. require_once 'Zend/Service/WindowsAzure/Exception.php';
  307. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  308. }
  309. if (!self::isValidContainerName($containerName)) {
  310. require_once 'Zend/Service/WindowsAzure/Exception.php';
  311. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  312. }
  313. // Headers
  314. $headers = array();
  315. // Acl specified?
  316. if ($acl != self::ACL_PRIVATE && !is_null($acl) && $acl != '') {
  317. $headers[Zend_Service_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-public-access'] = $acl;
  318. }
  319. // Policies
  320. $policies = null;
  321. if (is_array($signedIdentifiers) && count($signedIdentifiers) > 0) {
  322. $policies = '';
  323. $policies .= '<?xml version="1.0" encoding="utf-8"?>' . "\r\n";
  324. $policies .= '<SignedIdentifiers>' . "\r\n";
  325. foreach ($signedIdentifiers as $signedIdentifier) {
  326. $policies .= ' <SignedIdentifier>' . "\r\n";
  327. $policies .= ' <Id>' . $signedIdentifier->Id . '</Id>' . "\r\n";
  328. $policies .= ' <AccessPolicy>' . "\r\n";
  329. if ($signedIdentifier->Start != '')
  330. $policies .= ' <Start>' . $signedIdentifier->Start . '</Start>' . "\r\n";
  331. if ($signedIdentifier->Expiry != '')
  332. $policies .= ' <Expiry>' . $signedIdentifier->Expiry . '</Expiry>' . "\r\n";
  333. if ($signedIdentifier->Permissions != '')
  334. $policies .= ' <Permission>' . $signedIdentifier->Permissions . '</Permission>' . "\r\n";
  335. $policies .= ' </AccessPolicy>' . "\r\n";
  336. $policies .= ' </SignedIdentifier>' . "\r\n";
  337. }
  338. $policies .= '</SignedIdentifiers>' . "\r\n";
  339. }
  340. // Perform request
  341. $response = $this->_performRequest($containerName, '?restype=container&comp=acl', Zend_Http_Client::PUT, $headers, false, $policies, Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  342. if (!$response->isSuccessful()) {
  343. require_once 'Zend/Service/WindowsAzure/Exception.php';
  344. throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  345. }
  346. }
  347. /**
  348. * Get container
  349. *
  350. * @param string $containerName Container name
  351. * @return Zend_Service_WindowsAzure_Storage_BlobContainer
  352. * @throws Zend_Service_WindowsAzure_Exception
  353. */
  354. public function getContainer($containerName = '')
  355. {
  356. if ($containerName === '') {
  357. require_once 'Zend/Service/WindowsAzure/Exception.php';
  358. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  359. }
  360. if (!self::isValidContainerName($containerName)) {
  361. require_once 'Zend/Service/WindowsAzure/Exception.php';
  362. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  363. }
  364. // Perform request
  365. $response = $this->_performRequest($containerName, '?restype=container', Zend_Http_Client::GET, array(), false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
  366. if ($response->isSuccessful()) {
  367. // Parse metadata
  368. $metadata = $this->_parseMetadataHeaders($response->getHeaders());
  369. // Return container
  370. return new Zend_Service_WindowsAzure_Storage_BlobContainer(
  371. $containerName,
  372. $response->getHeader('Etag'),
  373. $response->getHeader('Last-modified'),
  374. $metadata
  375. );
  376. } else {
  377. require_once 'Zend/Service/WindowsAzure/Exception.php';
  378. throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  379. }
  380. }
  381. /**
  382. * Get container metadata
  383. *
  384. * @param string $containerName Container name
  385. * @return array Key/value pairs of meta data
  386. * @throws Zend_Service_WindowsAzure_Exception
  387. */
  388. public function getContainerMetadata($containerName = '')
  389. {
  390. if ($containerName === '') {
  391. require_once 'Zend/Service/WindowsAzure/Exception.php';
  392. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  393. }
  394. if (!self::isValidContainerName($containerName)) {
  395. require_once 'Zend/Service/WindowsAzure/Exception.php';
  396. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  397. }
  398. return $this->getContainer($containerName)->Metadata;
  399. }
  400. /**
  401. * Set container metadata
  402. *
  403. * 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.
  404. *
  405. * @param string $containerName Container name
  406. * @param array $metadata Key/value pairs of meta data
  407. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  408. * @throws Zend_Service_WindowsAzure_Exception
  409. */
  410. public function setContainerMetadata($containerName = '', $metadata = array(), $additionalHeaders = array())
  411. {
  412. if ($containerName === '') {
  413. require_once 'Zend/Service/WindowsAzure/Exception.php';
  414. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  415. }
  416. if (!self::isValidContainerName($containerName)) {
  417. require_once 'Zend/Service/WindowsAzure/Exception.php';
  418. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  419. }
  420. if (!is_array($metadata)) {
  421. require_once 'Zend/Service/WindowsAzure/Exception.php';
  422. throw new Zend_Service_WindowsAzure_Exception('Meta data should be an array of key and value pairs.');
  423. }
  424. if (count($metadata) == 0) {
  425. return;
  426. }
  427. // Create metadata headers
  428. $headers = array();
  429. $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
  430. // Additional headers?
  431. foreach ($additionalHeaders as $key => $value) {
  432. $headers[$key] = $value;
  433. }
  434. // Perform request
  435. $response = $this->_performRequest($containerName, '?restype=container&comp=metadata', Zend_Http_Client::PUT, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  436. if (!$response->isSuccessful()) {
  437. require_once 'Zend/Service/WindowsAzure/Exception.php';
  438. throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  439. }
  440. }
  441. /**
  442. * Delete container
  443. *
  444. * @param string $containerName Container name
  445. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  446. * @throws Zend_Service_WindowsAzure_Exception
  447. */
  448. public function deleteContainer($containerName = '', $additionalHeaders = array())
  449. {
  450. if ($containerName === '') {
  451. require_once 'Zend/Service/WindowsAzure/Exception.php';
  452. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  453. }
  454. if (!self::isValidContainerName($containerName)) {
  455. require_once 'Zend/Service/WindowsAzure/Exception.php';
  456. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  457. }
  458. // Additional headers?
  459. $headers = array();
  460. foreach ($additionalHeaders as $key => $value) {
  461. $headers[$key] = $value;
  462. }
  463. // Perform request
  464. $response = $this->_performRequest($containerName, '?restype=container', Zend_Http_Client::DELETE, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  465. if (!$response->isSuccessful()) {
  466. require_once 'Zend/Service/WindowsAzure/Exception.php';
  467. throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  468. }
  469. }
  470. /**
  471. * List containers
  472. *
  473. * @param string $prefix Optional. Filters the results to return only containers whose name begins with the specified prefix.
  474. * @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)
  475. * @param string $marker Optional string value that identifies the portion of the list to be returned with the next list operation.
  476. * @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')
  477. * @param int $currentResultCount Current result count (internal use)
  478. * @return array
  479. * @throws Zend_Service_WindowsAzure_Exception
  480. */
  481. public function listContainers($prefix = null, $maxResults = null, $marker = null, $include = null, $currentResultCount = 0)
  482. {
  483. // Build query string
  484. $queryString = array('comp=list');
  485. if (!is_null($prefix)) {
  486. $queryString[] = 'prefix=' . $prefix;
  487. }
  488. if (!is_null($maxResults)) {
  489. $queryString[] = 'maxresults=' . $maxResults;
  490. }
  491. if (!is_null($marker)) {
  492. $queryString[] = 'marker=' . $marker;
  493. }
  494. if (!is_null($include)) {
  495. $queryString[] = 'include=' . $include;
  496. }
  497. $queryString = self::createQueryStringFromArray($queryString);
  498. // Perform request
  499. $response = $this->_performRequest('', $queryString, Zend_Http_Client::GET, array(), false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_LIST);
  500. if ($response->isSuccessful()) {
  501. $xmlContainers = $this->_parseResponse($response)->Containers->Container;
  502. $xmlMarker = (string)$this->_parseResponse($response)->NextMarker;
  503. $containers = array();
  504. if (!is_null($xmlContainers)) {
  505. for ($i = 0; $i < count($xmlContainers); $i++) {
  506. $containers[] = new Zend_Service_WindowsAzure_Storage_BlobContainer(
  507. (string)$xmlContainers[$i]->Name,
  508. (string)$xmlContainers[$i]->Etag,
  509. (string)$xmlContainers[$i]->LastModified,
  510. $this->_parseMetadataElement($xmlContainers[$i])
  511. );
  512. }
  513. }
  514. $currentResultCount = $currentResultCount + count($containers);
  515. if (!is_null($maxResults) && $currentResultCount < $maxResults) {
  516. if (!is_null($xmlMarker) && $xmlMarker != '') {
  517. $containers = array_merge($containers, $this->listContainers($prefix, $maxResults, $xmlMarker, $include, $currentResultCount));
  518. }
  519. }
  520. if (!is_null($maxResults) && count($containers) > $maxResults) {
  521. $containers = array_slice($containers, 0, $maxResults);
  522. }
  523. return $containers;
  524. } else {
  525. require_once 'Zend/Service/WindowsAzure/Exception.php';
  526. throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  527. }
  528. }
  529. /**
  530. * Put blob
  531. *
  532. * @param string $containerName Container name
  533. * @param string $blobName Blob name
  534. * @param string $localFileName Local file name to be uploaded
  535. * @param array $metadata Key/value pairs of meta data
  536. * @param string $leaseId Lease identifier
  537. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  538. * @return object Partial blob properties
  539. * @throws Zend_Service_WindowsAzure_Exception
  540. */
  541. public function putBlob($containerName = '', $blobName = '', $localFileName = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
  542. {
  543. if ($containerName === '') {
  544. require_once 'Zend/Service/WindowsAzure/Exception.php';
  545. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  546. }
  547. if (!self::isValidContainerName($containerName)) {
  548. require_once 'Zend/Service/WindowsAzure/Exception.php';
  549. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  550. }
  551. if ($blobName === '') {
  552. require_once 'Zend/Service/WindowsAzure/Exception.php';
  553. throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.');
  554. }
  555. if ($localFileName === '') {
  556. require_once 'Zend/Service/WindowsAzure/Exception.php';
  557. throw new Zend_Service_WindowsAzure_Exception('Local file name is not specified.');
  558. }
  559. if (!file_exists($localFileName)) {
  560. require_once 'Zend/Service/WindowsAzure/Exception.php';
  561. throw new Zend_Service_WindowsAzure_Exception('Local file not found.');
  562. }
  563. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  564. require_once 'Zend/Service/WindowsAzure/Exception.php';
  565. throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  566. }
  567. // Check file size
  568. if (filesize($localFileName) >= self::MAX_BLOB_SIZE) {
  569. return $this->putLargeBlob($containerName, $blobName, $localFileName, $metadata, $leaseId, $additionalHeaders);
  570. }
  571. // Put the data to Windows Azure Storage
  572. return $this->putBlobData($containerName, $blobName, file_get_contents($localFileName), $metadata, $leaseId, $additionalHeaders);
  573. }
  574. /**
  575. * Put blob data
  576. *
  577. * @param string $containerName Container name
  578. * @param string $blobName Blob name
  579. * @param mixed $data Data to store
  580. * @param array $metadata Key/value pairs of meta data
  581. * @param string $leaseId Lease identifier
  582. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  583. * @return object Partial blob properties
  584. * @throws Zend_Service_WindowsAzure_Exception
  585. */
  586. public function putBlobData($containerName = '', $blobName = '', $data = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
  587. {
  588. if ($containerName === '') {
  589. require_once 'Zend/Service/WindowsAzure/Exception.php';
  590. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  591. }
  592. if (!self::isValidContainerName($containerName)) {
  593. require_once 'Zend/Service/WindowsAzure/Exception.php';
  594. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  595. }
  596. if ($blobName === '') {
  597. require_once 'Zend/Service/WindowsAzure/Exception.php';
  598. throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.');
  599. }
  600. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  601. require_once 'Zend/Service/WindowsAzure/Exception.php';
  602. throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  603. }
  604. // Create metadata headers
  605. $headers = array();
  606. if (!is_null($leaseId)) {
  607. $headers['x-ms-lease-id'] = $leaseId;
  608. }
  609. $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
  610. // Additional headers?
  611. foreach ($additionalHeaders as $key => $value) {
  612. $headers[$key] = $value;
  613. }
  614. // Specify blob type
  615. $headers[Zend_Service_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-type'] = self::BLOBTYPE_BLOCK;
  616. // Resource name
  617. $resourceName = self::createResourceName($containerName , $blobName);
  618. // Perform request
  619. $response = $this->_performRequest($resourceName, '', Zend_Http_Client::PUT, $headers, false, $data, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  620. if ($response->isSuccessful()) {
  621. return new Zend_Service_WindowsAzure_Storage_BlobInstance(
  622. $containerName,
  623. $blobName,
  624. null,
  625. $response->getHeader('Etag'),
  626. $response->getHeader('Last-modified'),
  627. $this->getBaseUrl() . '/' . $containerName . '/' . $blobName,
  628. strlen($data),
  629. '',
  630. '',
  631. '',
  632. false,
  633. $metadata
  634. );
  635. } else {
  636. require_once 'Zend/Service/WindowsAzure/Exception.php';
  637. throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  638. }
  639. }
  640. /**
  641. * Put large blob (> 64 MB)
  642. *
  643. * @param string $containerName Container name
  644. * @param string $blobName Blob name
  645. * @param string $localFileName Local file name to be uploaded
  646. * @param array $metadata Key/value pairs of meta data
  647. * @param string $leaseId Lease identifier
  648. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  649. * @return object Partial blob properties
  650. * @throws Zend_Service_WindowsAzure_Exception
  651. */
  652. public function putLargeBlob($containerName = '', $blobName = '', $localFileName = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
  653. {
  654. if ($containerName === '') {
  655. require_once 'Zend/Service/WindowsAzure/Exception.php';
  656. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  657. }
  658. if (!self::isValidContainerName($containerName)) {
  659. require_once 'Zend/Service/WindowsAzure/Exception.php';
  660. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  661. }
  662. if ($blobName === '') {
  663. require_once 'Zend/Service/WindowsAzure/Exception.php';
  664. throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.');
  665. }
  666. if ($localFileName === '') {
  667. require_once 'Zend/Service/WindowsAzure/Exception.php';
  668. throw new Zend_Service_WindowsAzure_Exception('Local file name is not specified.');
  669. }
  670. if (!file_exists($localFileName)) {
  671. require_once 'Zend/Service/WindowsAzure/Exception.php';
  672. throw new Zend_Service_WindowsAzure_Exception('Local file not found.');
  673. }
  674. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  675. require_once 'Zend/Service/WindowsAzure/Exception.php';
  676. throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  677. }
  678. // Check file size
  679. if (filesize($localFileName) < self::MAX_BLOB_SIZE) {
  680. return $this->putBlob($containerName, $blobName, $localFileName, $metadata, $leaseId, $additionalHeaders);
  681. }
  682. // Determine number of parts
  683. $numberOfParts = ceil( filesize($localFileName) / self::MAX_BLOB_TRANSFER_SIZE );
  684. // Generate block id's
  685. $blockIdentifiers = array();
  686. for ($i = 0; $i < $numberOfParts; $i++) {
  687. $blockIdentifiers[] = $this->_generateBlockId($i);
  688. }
  689. // Open file
  690. $fp = fopen($localFileName, 'r');
  691. if ($fp === false) {
  692. require_once 'Zend/Service/WindowsAzure/Exception.php';
  693. throw new Zend_Service_WindowsAzure_Exception('Could not open local file.');
  694. }
  695. // Upload parts
  696. for ($i = 0; $i < $numberOfParts; $i++) {
  697. // Seek position in file
  698. fseek($fp, $i * self::MAX_BLOB_TRANSFER_SIZE);
  699. // Read contents
  700. $fileContents = fread($fp, self::MAX_BLOB_TRANSFER_SIZE);
  701. // Put block
  702. $this->putBlock($containerName, $blobName, $blockIdentifiers[$i], $fileContents, $leaseId);
  703. // Dispose file contents
  704. $fileContents = null;
  705. unset($fileContents);
  706. }
  707. // Close file
  708. fclose($fp);
  709. // Put block list
  710. $this->putBlockList($containerName, $blobName, $blockIdentifiers, $metadata, $leaseId, $additionalHeaders);
  711. // Return information of the blob
  712. return $this->getBlobInstance($containerName, $blobName, null, $leaseId);
  713. }
  714. /**
  715. * Put large blob block
  716. *
  717. * @param string $containerName Container name
  718. * @param string $blobName Blob name
  719. * @param string $identifier Block ID
  720. * @param array $contents Contents of the block
  721. * @param string $leaseId Lease identifier
  722. * @throws Zend_Service_WindowsAzure_Exception
  723. */
  724. public function putBlock($containerName = '', $blobName = '', $identifier = '', $contents = '', $leaseId = null)
  725. {
  726. if ($containerName === '') {
  727. require_once 'Zend/Service/WindowsAzure/Exception.php';
  728. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  729. }
  730. if (!self::isValidContainerName($containerName)) {
  731. require_once 'Zend/Service/WindowsAzure/Exception.php';
  732. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  733. }
  734. if ($identifier === '') {
  735. require_once 'Zend/Service/WindowsAzure/Exception.php';
  736. throw new Zend_Service_WindowsAzure_Exception('Block identifier is not specified.');
  737. }
  738. if (strlen($contents) > self::MAX_BLOB_TRANSFER_SIZE) {
  739. require_once 'Zend/Service/WindowsAzure/Exception.php';
  740. throw new Zend_Service_WindowsAzure_Exception('Block size is too big.');
  741. }
  742. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  743. require_once 'Zend/Service/WindowsAzure/Exception.php';
  744. throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  745. }
  746. // Headers
  747. $headers = array();
  748. if (!is_null($leaseId)) {
  749. $headers['x-ms-lease-id'] = $leaseId;
  750. }
  751. // Resource name
  752. $resourceName = self::createResourceName($containerName , $blobName);
  753. // Upload
  754. $response = $this->_performRequest($resourceName, '?comp=block&blockid=' . base64_encode($identifier), Zend_Http_Client::PUT, $headers, false, $contents, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  755. if (!$response->isSuccessful()) {
  756. require_once 'Zend/Service/WindowsAzure/Exception.php';
  757. throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  758. }
  759. }
  760. /**
  761. * Put block list
  762. *
  763. * @param string $containerName Container name
  764. * @param string $blobName Blob name
  765. * @param array $blockList Array of block identifiers
  766. * @param array $metadata Key/value pairs of meta data
  767. * @param string $leaseId Lease identifier
  768. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  769. * @throws Zend_Service_WindowsAzure_Exception
  770. */
  771. public function putBlockList($containerName = '', $blobName = '', $blockList = array(), $metadata = array(), $leaseId = null, $additionalHeaders = array())
  772. {
  773. if ($containerName === '') {
  774. require_once 'Zend/Service/WindowsAzure/Exception.php';
  775. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  776. }
  777. if (!self::isValidContainerName($containerName)) {
  778. require_once 'Zend/Service/WindowsAzure/Exception.php';
  779. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  780. }
  781. if ($blobName === '') {
  782. require_once 'Zend/Service/WindowsAzure/Exception.php';
  783. throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.');
  784. }
  785. if (count($blockList) == 0) {
  786. require_once 'Zend/Service/WindowsAzure/Exception.php';
  787. throw new Zend_Service_WindowsAzure_Exception('Block list does not contain any elements.');
  788. }
  789. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  790. require_once 'Zend/Service/WindowsAzure/Exception.php';
  791. throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  792. }
  793. // Generate block list
  794. $blocks = '';
  795. foreach ($blockList as $block) {
  796. $blocks .= ' <Latest>' . base64_encode($block) . '</Latest>' . "\n";
  797. }
  798. // Generate block list request
  799. $fileContents = utf8_encode(implode("\n", array(
  800. '<?xml version="1.0" encoding="utf-8"?>',
  801. '<BlockList>',
  802. $blocks,
  803. '</BlockList>'
  804. )));
  805. // Create metadata headers
  806. $headers = array();
  807. if (!is_null($leaseId)) {
  808. $headers['x-ms-lease-id'] = $leaseId;
  809. }
  810. $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
  811. // Additional headers?
  812. foreach ($additionalHeaders as $key => $value) {
  813. $headers[$key] = $value;
  814. }
  815. // Resource name
  816. $resourceName = self::createResourceName($containerName , $blobName);
  817. // Perform request
  818. $response = $this->_performRequest($resourceName, '?comp=blocklist', Zend_Http_Client::PUT, $headers, false, $fileContents, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  819. if (!$response->isSuccessful()) {
  820. require_once 'Zend/Service/WindowsAzure/Exception.php';
  821. throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  822. }
  823. }
  824. /**
  825. * Get block list
  826. *
  827. * @param string $containerName Container name
  828. * @param string $blobName Blob name
  829. * @param string $snapshotId Snapshot identifier
  830. * @param string $leaseId Lease identifier
  831. * @param integer $type Type of block list to retrieve. 0 = all, 1 = committed, 2 = uncommitted
  832. * @return array
  833. * @throws Zend_Service_WindowsAzure_Exception
  834. */
  835. public function getBlockList($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null, $type = 0)
  836. {
  837. if ($containerName === '') {
  838. require_once 'Zend/Service/WindowsAzure/Exception.php';
  839. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  840. }
  841. if (!self::isValidContainerName($containerName)) {
  842. require_once 'Zend/Service/WindowsAzure/Exception.php';
  843. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  844. }
  845. if ($blobName === '') {
  846. require_once 'Zend/Service/WindowsAzure/Exception.php';
  847. throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.');
  848. }
  849. if ($type < 0 || $type > 2) {
  850. require_once 'Zend/Service/WindowsAzure/Exception.php';
  851. throw new Zend_Service_WindowsAzure_Exception('Invalid type of block list to retrieve.');
  852. }
  853. // Set $blockListType
  854. $blockListType = 'all';
  855. if ($type == 1) {
  856. $blockListType = 'committed';
  857. }
  858. if ($type == 2) {
  859. $blockListType = 'uncommitted';
  860. }
  861. // Headers
  862. $headers = array();
  863. if (!is_null($leaseId)) {
  864. $headers['x-ms-lease-id'] = $leaseId;
  865. }
  866. // Build query string
  867. $queryString = array('comp=blocklist', 'blocklisttype=' . $blockListType);
  868. if (!is_null($snapshotId)) {
  869. $queryString[] = 'snapshot=' . $snapshotId;
  870. }
  871. $queryString = self::createQueryStringFromArray($queryString);
  872. // Resource name
  873. $resourceName = self::createResourceName($containerName , $blobName);
  874. // Perform request
  875. $response = $this->_performRequest($resourceName, $queryString, Zend_Http_Client::GET, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
  876. if ($response->isSuccessful()) {
  877. // Parse response
  878. $blockList = $this->_parseResponse($response);
  879. // Create return value
  880. $returnValue = array();
  881. if ($blockList->CommittedBlocks) {
  882. foreach ($blockList->CommittedBlocks->Block as $block) {
  883. $returnValue['CommittedBlocks'][] = (object)array(
  884. 'Name' => (string)$block->Name,
  885. 'Size' => (string)$block->Size
  886. );
  887. }
  888. }
  889. if ($blockList->UncommittedBlocks) {
  890. foreach ($blockList->UncommittedBlocks->Block as $block) {
  891. $returnValue['UncommittedBlocks'][] = (object)array(
  892. 'Name' => (string)$block->Name,
  893. 'Size' => (string)$block->Size
  894. );
  895. }
  896. }
  897. return $returnValue;
  898. } else {
  899. require_once 'Zend/Service/WindowsAzure/Exception.php';
  900. throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  901. }
  902. }
  903. /**
  904. * Create page blob
  905. *
  906. * @param string $containerName Container name
  907. * @param string $blobName Blob name
  908. * @param int $size Size of the page blob in bytes
  909. * @param array $metadata Key/value pairs of meta data
  910. * @param string $leaseId Lease identifier
  911. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  912. * @return object Partial blob properties
  913. * @throws Zend_Service_WindowsAzure_Exception
  914. */
  915. public function createPageBlob($containerName = '', $blobName = '', $size = 0, $metadata = array(), $leaseId = null, $additionalHeaders = array())
  916. {
  917. if ($containerName === '') {
  918. require_once 'Zend/Service/WindowsAzure/Exception.php';
  919. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  920. }
  921. if (!self::isValidContainerName($containerName)) {
  922. require_once 'Zend/Service/WindowsAzure/Exception.php';
  923. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  924. }
  925. if ($blobName === '') {
  926. require_once 'Zend/Service/WindowsAzure/Exception.php';
  927. throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.');
  928. }
  929. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  930. require_once 'Zend/Service/WindowsAzure/Exception.php';
  931. throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  932. }
  933. if ($size <= 0) {
  934. require_once 'Zend/Service/WindowsAzure/Exception.php';
  935. throw new Zend_Service_WindowsAzure_Exception('Page blob size must be specified.');
  936. }
  937. // Create metadata headers
  938. $headers = array();
  939. if (!is_null($leaseId)) {
  940. $headers['x-ms-lease-id'] = $leaseId;
  941. }
  942. $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
  943. // Additional headers?
  944. foreach ($additionalHeaders as $key => $value) {
  945. $headers[$key] = $value;
  946. }
  947. // Specify blob type & blob length
  948. $headers[Zend_Service_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-type'] = self::BLOBTYPE_PAGE;
  949. $headers[Zend_Service_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-content-length'] = $size;
  950. $headers['Content-Length'] = 0;
  951. // Resource name
  952. $resourceName = self::createResourceName($containerName , $blobName);
  953. // Perform request
  954. $response = $this->_performRequest($resourceName, '', Zend_Http_Client::PUT, $headers, false, '', Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  955. if ($response->isSuccessful()) {
  956. return new Zend_Service_WindowsAzure_Storage_BlobInstance(
  957. $containerName,
  958. $blobName,
  959. null,
  960. $response->getHeader('Etag'),
  961. $response->getHeader('Last-modified'),
  962. $this->getBaseUrl() . '/' . $containerName . '/' . $blobName,
  963. $size,
  964. '',
  965. '',
  966. '',
  967. false,
  968. $metadata
  969. );
  970. } else {
  971. require_once 'Zend/Service/WindowsAzure/Exception.php';
  972. throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  973. }
  974. }
  975. /**
  976. * Put page in page blob
  977. *
  978. * @param string $containerName Container name
  979. * @param string $blobName Blob name
  980. * @param int $startByteOffset Start byte offset
  981. * @param int $endByteOffset End byte offset
  982. * @param mixed $contents Page contents
  983. * @param string $writeMethod Write method (Zend_Service_WindowsAzure_Storage_Blob::PAGE_WRITE_*)
  984. * @param string $leaseId Lease identifier
  985. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  986. * @throws Zend_Service_WindowsAzure_Exception
  987. */
  988. public function putPage($containerName = '', $blobName = '', $startByteOffset = 0, $endByteOffset = 0, $contents = '', $writeMethod = self::PAGE_WRITE_UPDATE, $leaseId = null, $additionalHeaders = array())
  989. {
  990. if ($containerName === '') {
  991. require_once 'Zend/Service/WindowsAzure/Exception.php';
  992. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  993. }
  994. if (!self::isValidContainerName($containerName)) {
  995. require_once 'Zend/Service/WindowsAzure/Exception.php';
  996. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  997. }
  998. if ($blobName === '') {
  999. require_once 'Zend/Service/WindowsAzure/Exception.php';
  1000. throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.');
  1001. }
  1002. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  1003. require_once 'Zend/Service/WindowsAzure/Exception.php';
  1004. throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1005. }
  1006. if ($startByteOffset % 512 != 0) {
  1007. require_once 'Zend/Service/WindowsAzure/Exception.php';
  1008. throw new Zend_Service_WindowsAzure_Exception('Start byte offset must be a modulus of 512.');
  1009. }
  1010. if (($endByteOffset + 1) % 512 != 0) {
  1011. require_once 'Zend/Service/WindowsAzure/Exception.php';
  1012. throw new Zend_Service_WindowsAzure_Exception('End byte offset must be a modulus of 512 minus 1.');
  1013. }
  1014. // Determine size
  1015. $size = strlen($contents);
  1016. if ($size >= self::MAX_BLOB_TRANSFER_SIZE) {
  1017. require_once 'Zend/Service/WindowsAzure/Exception.php';
  1018. throw new Zend_Service_WindowsAzure_Exception('Page blob size must not be larger than ' + self::MAX_BLOB_TRANSFER_SIZE . ' bytes.');
  1019. }
  1020. // Create metadata headers
  1021. $headers = array();
  1022. if (!is_null($leaseId)) {
  1023. $headers['x-ms-lease-id'] = $leaseId;
  1024. }
  1025. // Additional headers?
  1026. foreach ($additionalHeaders as $key => $value) {
  1027. $headers[$key] = $value;
  1028. }
  1029. // Specify range
  1030. $headers['Range'] = 'bytes=' . $startByteOffset . '-' . $endByteOffset;
  1031. // Write method
  1032. $headers[Zend_Service_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'page-write'] = $writeMethod;
  1033. // Resource name
  1034. $resourceName = self::createResourceName($containerName , $blobName);
  1035. // Perform request
  1036. $response = $this->_performRequest($resourceName, '?comp=page', Zend_Http_Client::PUT, $headers, false, $contents, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  1037. if (!$response->isSuccessful()) {
  1038. require_once 'Zend/Service/WindowsAzure/Exception.php';
  1039. throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  1040. }
  1041. }
  1042. /**
  1043. * Put page in page blob
  1044. *
  1045. * @param string $containerName Container name
  1046. * @param string $blobName Blob name
  1047. * @param int $startByteOffset Start byte offset
  1048. * @param int $endByteOffset End byte offset
  1049. * @param string $leaseId Lease identifier
  1050. * @return array Array of page ranges
  1051. * @throws Zend_Service_WindowsAzure_Exception
  1052. */
  1053. public function getPageRegions($containerName = '', $blobName = '', $startByteOffset = 0, $endByteOffset = 0, $leaseId = null)
  1054. {
  1055. if ($containerName === '') {
  1056. require_once 'Zend/Service/WindowsAzure/Exception.php';
  1057. throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.');
  1058. }
  1059. if (!self::isValidContainerName($containerName)) {
  1060. require_once 'Zend/Service/WindowsAzure/Exception.php';
  1061. throw new Zend_Service_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1062. }
  1063. if ($blobName === '') {
  1064. require_once 'Zend/Service/WindowsAzure/Exception.php';
  1065. throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.');
  1066. }
  1067. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  1068. require_once 'Zend/Service/WindowsAzure/Exception.php';
  1069. throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1070. }
  1071. if ($startByteOffset % 512 != 0) {
  1072. require_once 'Zend/Service/WindowsAzure/Exception.php';
  1073. throw new Zend_Service_WindowsAzure_Exception('Start byte offset must be a modulus of 512.');
  1074. }
  1075. if ($endByteOffset > 0 && ($endByteOffset + 1) % 512 != 0) {
  1076. require_once 'Zend/Service/WindowsAzure/Exception.php';
  1077. throw new Zend_Service_WindowsAzure_Exception('End byte offset must be a modulus of 512 minus 1.');
  1078. }
  1079. // Create metadata headers
  1080. $headers = array();
  1081. if (!is_null($leaseId)) {
  1082. $headers['x-ms-lease-id'] = $leaseId;
  1083. }
  1084. // Specify range?
  1085. if ($endByteOffset > 0) {
  1086. $headers['Range'] = 'bytes=' . $startByteOffset . '-' . $endByteOffset;
  1087. }
  1088. // Resource name
  1089. $resourceName = self::createResourceName($containerName , $blobName);
  1090. // Perform request
  1091. $response = $this->_performRequest($resourceName, '?comp=pagelist', Zend_Http_Client::GET, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  1092. if ($response->isSuccessful()) {
  1093. $result = $this->_parseResponse($response);
  1094. $xmlRanges = null;
  1095. if (count($result->PageRange) > 1) {
  1096. $xmlRanges = $result->PageRange;
  1097. } else {
  1098. $xmlRanges = array($result->PageRange);
  1099. }
  1100. $ranges = array();
  1101. for ($i = 0; $i < count($xmlRanges); $i++) {
  1102. $ranges[] = new Zend_Service_WindowsAzure_Storage_PageRegionInstance(
  1103. (int)$xmlRanges[$i]->Start,
  1104. (int)$xmlRanges[$i]->End
  1105. );
  1106. }
  1107. return $ranges;
  1108. } else {
  1109. require_once 'Zend/Service/WindowsAzure/Exception.php';
  1110. throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed…

Large files files are truncated, but you can click here to view the full file