Google_Http_MediaFileUpload

Manage large file uploads, which may be media but can be any type of sizable data.

Defined (1)

The class is defined in the following location(s).

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