s3browserupload.class.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. /*
  3. * Copyright 2010-2011 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License").
  6. * You may not use this file except in compliance with the License.
  7. * A copy of the License is located at
  8. *
  9. * http://aws.amazon.com/apache2.0
  10. *
  11. * or in the "license" file accompanying this file. This file is distributed
  12. * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  13. * express or implied. See the License for the specific language governing
  14. * permissions and limitations under the License.
  15. */
  16. class S3BrowserUpload extends AmazonS3
  17. {
  18. /**
  19. * The <code>POST</code> operation adds an object to a specified bucket using HTML forms. POST is an alternate
  20. * form of <code>PUT</code> that enables browser-based uploads as a way of putting objects in buckets.
  21. * Parameters that are passed to <code>PUT</code> via HTTP headers are instead passed as form fields to
  22. * <code>POST</code> in the <code>multipart/form-data</code> encoded message body. You must have
  23. * <code>WRITE</code> access on a bucket to add an object to it. Amazon S3 never stores partial objects: if
  24. * you receive a successful response, you can be confident the entire object was stored.
  25. *
  26. * @param string $bucket (Required) The name of the bucket to use.
  27. * @param string|integer $expires (Optional) The point in time when the upload form field should expire. The default value is <code>+1 hour</code>.
  28. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  29. * <li><code>acl</code> - <code>string</code> - Optional - The access control setting to apply to the uploaded file. Accepts any of the following constants: [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>].</li>
  30. * <li><code>Cache-Control</code> - <code>string</code> - Optional - The Cache-Control HTTP header value to apply to the uploaded file. To use a <code>starts-with</code> comparison instead of an <code>equals</code> comparison, prefix the value with a <code>^</code> (carat) character.</li>
  31. * <li><code>Content-Disposition</code> - <code>string</code> - Optional - The Content-Disposition HTTP header value to apply to the uploaded file. To use a <code>starts-with</code> comparison instead of an <code>equals</code> comparison, prefix the value with a <code>^</code> (carat) character.</li>
  32. * <li><code>Content-Encoding</code> - <code>string</code> - Optional - The Content-Encoding HTTP header value to apply to the uploaded file. To use a <code>starts-with</code> comparison instead of an <code>equals</code> comparison, prefix the value with a <code>^</code> (carat) character.</li>
  33. * <li><code>Content-Type</code> - <code>string</code> - Optional - The Content-Type HTTP header value to apply to the uploaded file. The default value is <code>application/octet-stream</code>. To use a <code>starts-with</code> comparison instead of an <code>equals</code> comparison, prefix the value with a <code>^</code> (carat) character.</li>
  34. * <li><code>Expires</code> - <code>string</code> - Optional - The Expires HTTP header value to apply to the uploaded file. To use a <code>starts-with</code> comparison instead of an <code>equals</code> comparison, prefix the value with a <code>^</code> (carat) character.</li>
  35. * <li><code>key</code> - <code>string</code> - Optional - The location where the file should be uploaded to. The default value is <code>${filename}</code>.</li>
  36. * <li><code>success_action_redirect</code> - <code>string</code> - Optional - The URI for Amazon S3 to redirect to upon successful upload.</li>
  37. * <li><code>success_action_status</code> - <code>integer</code> - Optional - The status code for Amazon S3 to return upon successful upload.</li>
  38. * <li><code>x-amz-storage-class</code> - <code>string</code> - Optional - The storage setting to apply to the object. [Allowed values: <code>AmazonS3::STORAGE_STANDARD</code>, <code>AmazonS3::STORAGE_REDUCED</code>]. The default value is <code>AmazonS3::STORAGE_STANDARD</code>.</li>
  39. * <li>x-amz-meta-*</li>
  40. * </ul>
  41. * @return array An array of fields that can be converted into markup.
  42. * @link http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectPOST.html POST Object
  43. */
  44. public function generate_upload_parameters($bucket, $expires = '+1 hour', $opt = null)
  45. {
  46. if (!$opt) $opt = array();
  47. // Policy document
  48. $policy = array(
  49. 'conditions' => array(
  50. array('bucket' => $bucket),
  51. )
  52. );
  53. // Basic form
  54. $form = array();
  55. $form['form'] = array(
  56. 'action' => $bucket . '.s3.amazonaws.com',
  57. 'method' => 'POST',
  58. 'enctype' => 'multipart/form-data'
  59. );
  60. // Inputs
  61. $form['inputs'] = array(
  62. 'AWSAccessKeyId' => $this->key
  63. );
  64. // Expires
  65. if ($expires)
  66. {
  67. if (is_numeric($expires))
  68. {
  69. $expires = gmdate('j M Y, g:i a Z', (integer) $expires);
  70. }
  71. $expires = $this->util->convert_date_to_iso8601($expires);
  72. $policy['expiration'] = (string) $expires;
  73. }
  74. // Default values
  75. if (!isset($opt['key']))
  76. {
  77. $opt['key'] = '${filename}';
  78. }
  79. // Success Action Status
  80. if (isset($opt['success_action_status']) && !empty($opt['success_action_status']))
  81. {
  82. $form['inputs']['success_action_status'] = (string) $opt['success_action_status'];
  83. $policy['conditions'][] = array(
  84. 'success_action_status' => (string) $opt['success_action_status']
  85. );
  86. unset($opt['success_action_status']);
  87. }
  88. // Other parameters
  89. foreach ($opt as $param_key => $param_value)
  90. {
  91. if ($param_value[0] === '^')
  92. {
  93. $form['inputs'][$param_key] = substr((string) $param_value, 1);
  94. $param_value = preg_replace('/\$\{(\w*)\}/', '', (string) $param_value);
  95. $policy['conditions'][] = array('starts-with', '$' . $param_key, (substr((string) $param_value, 1) ? substr((string) $param_value, 1) : ''));
  96. }
  97. else
  98. {
  99. $form['inputs'][$param_key] = (string) $param_value;
  100. $policy['conditions'][] = array(
  101. $param_key => (string) $param_value
  102. );
  103. }
  104. }
  105. // Add policy
  106. $json_policy = json_encode($policy);
  107. $json_policy_b64 = base64_encode($json_policy);
  108. $form['inputs']['policy'] = $json_policy_b64;
  109. $form['metadata']['json_policy'] = $json_policy;
  110. // Add signature
  111. $form['inputs']['signature'] = base64_encode(hash_hmac('sha1', $json_policy_b64, $this->secret_key, true));
  112. return $form;
  113. }
  114. /*%******************************************************************************************%*/
  115. // HELPERS
  116. /**
  117. * Returns the protocol of the web page that this script is currently running on. This method only works
  118. * correctly when run from a publicly-accessible web page.
  119. */
  120. public static function protocol()
  121. {
  122. return (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) === 'on') ? 'https://' : 'http://';
  123. }
  124. /**
  125. * Returns the domain (and port) of the web page that this script is currently running on. This method
  126. * only works correctly when run from a publicly-accessible web page.
  127. */
  128. public static function domain()
  129. {
  130. if (isset($_SERVER['SERVER_NAME']) && isset($_SERVER['SERVER_PORT']))
  131. {
  132. return $_SERVER['SERVER_NAME'] . ((integer) $_SERVER['SERVER_PORT'] === 80 ? '' : ':' . $_SERVER['SERVER_PORT']);
  133. }
  134. return null;
  135. }
  136. /**
  137. * Returns the URI of the web page that this script is currently running on. This method only works
  138. * correctly when run from a publicly-accessible web page.
  139. */
  140. public static function current_uri()
  141. {
  142. if (isset($_SERVER['REQUEST_URI']))
  143. {
  144. $uri = self::protocol();
  145. $uri .= self::domain();
  146. $uri .= $_SERVER['REQUEST_URI'];
  147. return $uri;
  148. }
  149. return null;
  150. }
  151. }