[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/google/Google/Http/ -> MediaFileUpload.php (source)

   1  <?php
   2  /**
   3   * Copyright 2012 Google Inc.
   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   * You may obtain a copy of the License at
   8   *
   9   *     http://www.apache.org/licenses/LICENSE-2.0
  10   *
  11   * Unless required by applicable law or agreed to in writing, software
  12   * distributed under the License is distributed on an "AS IS" BASIS,
  13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14   * See the License for the specific language governing permissions and
  15   * limitations under the License.
  16   */
  17  
  18  require_once  'Google/Client.php';
  19  require_once 'Google/Exception.php';
  20  require_once 'Google/Http/Request.php';
  21  require_once 'Google/Http/REST.php';
  22  require_once 'Google/Utils.php';
  23  
  24  /**
  25   * @author Chirag Shah <[email protected]>
  26   *
  27   */
  28  class Google_Http_MediaFileUpload
  29  {
  30    const UPLOAD_MEDIA_TYPE = 'media';
  31    const UPLOAD_MULTIPART_TYPE = 'multipart';
  32    const UPLOAD_RESUMABLE_TYPE = 'resumable';
  33  
  34    /** @var string $mimeType */
  35    private $mimeType;
  36  
  37    /** @var string $data */
  38    private $data;
  39  
  40    /** @var bool $resumable */
  41    private $resumable;
  42  
  43    /** @var int $chunkSize */
  44    private $chunkSize;
  45  
  46    /** @var int $size */
  47    private $size;
  48  
  49    /** @var string $resumeUri */
  50    private $resumeUri;
  51  
  52    /** @var int $progress */
  53    private $progress;
  54  
  55    /** @var Google_Client */
  56    private $client;
  57  
  58    /** @var Google_Http_Request */
  59    private $request;
  60  
  61    /** @var string */
  62    private $boundary;
  63  
  64    /**
  65     * Result code from last HTTP call
  66     * @var int
  67     */
  68    private $httpResultCode;
  69  
  70    /**
  71     * @param $mimeType string
  72     * @param $data string The bytes you want to upload.
  73     * @param $resumable bool
  74     * @param bool $chunkSize File will be uploaded in chunks of this many bytes.
  75     * only used if resumable=True
  76     */
  77    public function __construct(
  78        Google_Client $client,
  79        Google_Http_Request $request,
  80        $mimeType,
  81        $data,
  82        $resumable = false,
  83        $chunkSize = false,
  84        $boundary = false
  85    ) {
  86      $this->client = $client;
  87      $this->request = $request;
  88      $this->mimeType = $mimeType;
  89      $this->data = $data;
  90      $this->size = strlen($this->data);
  91      $this->resumable = $resumable;
  92      if (!$chunkSize) {
  93        $chunkSize = 256 * 1024;
  94      }
  95      $this->chunkSize = $chunkSize;
  96      $this->progress = 0;
  97      $this->boundary = $boundary;
  98  
  99      // Process Media Request
 100      $this->process();
 101    }
 102  
 103    /**
 104     * Set the size of the file that is being uploaded.
 105     * @param $size - int file size in bytes
 106     */
 107    public function setFileSize($size)
 108    {
 109      $this->size = $size;
 110    }
 111  
 112    /**
 113     * Return the progress on the upload
 114     * @return int progress in bytes uploaded.
 115     */
 116    public function getProgress()
 117    {
 118      return $this->progress;
 119    }
 120  
 121    /**
 122     * Return the HTTP result code from the last call made.
 123     * @return int code
 124     */
 125    public function getHttpResultCode()
 126    {
 127      return $this->httpResultCode;
 128    }
 129  
 130    /**
 131     * Send the next part of the file to upload.
 132     * @param [$chunk] the next set of bytes to send. If false will used $data passed
 133     * at construct time.
 134     */
 135    public function nextChunk($chunk = false)
 136    {
 137      if (false == $this->resumeUri) {
 138        $this->resumeUri = $this->getResumeUri();
 139      }
 140  
 141      if (false == $chunk) {
 142        $chunk = substr($this->data, $this->progress, $this->chunkSize);
 143      }
 144  
 145      $lastBytePos = $this->progress + strlen($chunk) - 1;
 146      $headers = array(
 147        'content-range' => "bytes $this->progress-$lastBytePos/$this->size",
 148        'content-type' => $this->request->getRequestHeader('content-type'),
 149        'content-length' => $this->chunkSize,
 150        'expect' => '',
 151      );
 152  
 153      $httpRequest = new Google_Http_Request(
 154          $this->resumeUri,
 155          'PUT',
 156          $headers,
 157          $chunk
 158      );
 159  
 160      if ($this->client->getClassConfig("Google_Http_Request", "enable_gzip_for_uploads")) {
 161        $httpRequest->enableGzip();
 162      } else {
 163        $httpRequest->disableGzip();
 164      }
 165  
 166      $response = $this->client->getIo()->makeRequest($httpRequest);
 167      $response->setExpectedClass($this->request->getExpectedClass());
 168      $code = $response->getResponseHttpCode();
 169      $this->httpResultCode = $code;
 170  
 171      if (308 == $code) {
 172        // Track the amount uploaded.
 173        $range = explode('-', $response->getResponseHeader('range'));
 174        $this->progress = $range[1] + 1;
 175  
 176        // Allow for changing upload URLs.
 177        $location = $response->getResponseHeader('location');
 178        if ($location) {
 179          $this->resumeUri = $location;
 180        }
 181  
 182        // No problems, but upload not complete.
 183        return false;
 184      } else {
 185        return Google_Http_REST::decodeHttpResponse($response);
 186      }
 187    }
 188  
 189    /**
 190     * @param $meta
 191     * @param $params
 192     * @return array|bool
 193     * @visible for testing
 194     */
 195    private function process()
 196    {
 197      $postBody = false;
 198      $contentType = false;
 199  
 200      $meta = $this->request->getPostBody();
 201      $meta = is_string($meta) ? json_decode($meta, true) : $meta;
 202  
 203      $uploadType = $this->getUploadType($meta);
 204      $this->request->setQueryParam('uploadType', $uploadType);
 205      $this->transformToUploadUrl();
 206      $mimeType = $this->mimeType ?
 207          $this->mimeType :
 208          $this->request->getRequestHeader('content-type');
 209  
 210      if (self::UPLOAD_RESUMABLE_TYPE == $uploadType) {
 211        $contentType = $mimeType;
 212        $postBody = is_string($meta) ? $meta : json_encode($meta);
 213      } else if (self::UPLOAD_MEDIA_TYPE == $uploadType) {
 214        $contentType = $mimeType;
 215        $postBody = $this->data;
 216      } else if (self::UPLOAD_MULTIPART_TYPE == $uploadType) {
 217        // This is a multipart/related upload.
 218        $boundary = $this->boundary ? $this->boundary : mt_rand();
 219        $boundary = str_replace('"', '', $boundary);
 220        $contentType = 'multipart/related; boundary=' . $boundary;
 221        $related = "--$boundary\r\n";
 222        $related .= "Content-Type: application/json; charset=UTF-8\r\n";
 223        $related .= "\r\n" . json_encode($meta) . "\r\n";
 224        $related .= "--$boundary\r\n";
 225        $related .= "Content-Type: $mimeType\r\n";
 226        $related .= "Content-Transfer-Encoding: base64\r\n";
 227        $related .= "\r\n" . base64_encode($this->data) . "\r\n";
 228        $related .= "--$boundary--";
 229        $postBody = $related;
 230      }
 231  
 232      $this->request->setPostBody($postBody);
 233  
 234      if (isset($contentType) && $contentType) {
 235        $contentTypeHeader['content-type'] = $contentType;
 236        $this->request->setRequestHeaders($contentTypeHeader);
 237      }
 238    }
 239  
 240    private function transformToUploadUrl()
 241    {
 242      $base = $this->request->getBaseComponent();
 243      $this->request->setBaseComponent($base . '/upload');
 244    }
 245  
 246    /**
 247     * Valid upload types:
 248     * - resumable (UPLOAD_RESUMABLE_TYPE)
 249     * - media (UPLOAD_MEDIA_TYPE)
 250     * - multipart (UPLOAD_MULTIPART_TYPE)
 251     * @param $meta
 252     * @return string
 253     * @visible for testing
 254     */
 255    public function getUploadType($meta)
 256    {
 257      if ($this->resumable) {
 258        return self::UPLOAD_RESUMABLE_TYPE;
 259      }
 260  
 261      if (false == $meta && $this->data) {
 262        return self::UPLOAD_MEDIA_TYPE;
 263      }
 264  
 265      return self::UPLOAD_MULTIPART_TYPE;
 266    }
 267  
 268    private function getResumeUri()
 269    {
 270      $result = null;
 271      $body = $this->request->getPostBody();
 272      if ($body) {
 273        $headers = array(
 274          'content-type' => 'application/json; charset=UTF-8',
 275          'content-length' => Google_Utils::getStrLen($body),
 276          'x-upload-content-type' => $this->mimeType,
 277          'x-upload-content-length' => $this->size,
 278          'expect' => '',
 279        );
 280        $this->request->setRequestHeaders($headers);
 281      }
 282  
 283      $response = $this->client->getIo()->makeRequest($this->request);
 284      $location = $response->getResponseHeader('location');
 285      $code = $response->getResponseHttpCode();
 286  
 287      if (200 == $code && true == $location) {
 288        return $location;
 289      }
 290      throw new Google_Exception("Failed to start the resumable upload");
 291    }
 292  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1