private function uploadChunks($file_phid, $path) { $conduit = $this->getConduit(); $f = @fopen($path, 'rb'); if (!$f) { throw new Exception(pht('Unable to open file "%s"', $path)); } $this->writeStatus(pht('Beginning chunked upload of large file...')); $chunks = $conduit->callMethodSynchronous('file.querychunks', array('filePHID' => $file_phid)); $remaining = array(); foreach ($chunks as $chunk) { if (!$chunk['complete']) { $remaining[] = $chunk; } } $done = count($chunks) - count($remaining); if ($done) { $this->writeStatus(pht('Resuming upload (%d of %d chunks remain).', new PhutilNumber(count($remaining)), new PhutilNumber(count($chunks)))); } else { $this->writeStatus(pht('Uploading chunks (%d chunks to upload).', new PhutilNumber(count($remaining)))); } $progress = new PhutilConsoleProgressBar(); $progress->setTotal(count($chunks)); for ($ii = 0; $ii < $done; $ii++) { $progress->update(1); } $progress->draw(); // TODO: We could do these in parallel to improve upload performance. foreach ($remaining as $chunk) { $offset = $chunk['byteStart']; $ok = fseek($f, $offset); if ($ok !== 0) { throw new Exception(pht('Failed to %s!', 'fseek()')); } $data = fread($f, $chunk['byteEnd'] - $chunk['byteStart']); if ($data === false) { throw new Exception(pht('Failed to %s!', 'fread()')); } $conduit->callMethodSynchronous('file.uploadchunk', array('filePHID' => $file_phid, 'byteStart' => $offset, 'dataEncoding' => 'base64', 'data' => base64_encode($data))); $progress->update(1); } }
/** * Upload missing chunks of a large file by calling `file.uploadchunk` over * Conduit. * * @task internal */ private function uploadChunks(ArcanistFileDataRef $file, $file_phid) { $conduit = $this->conduit; $chunks = $conduit->callMethodSynchronous('file.querychunks', array('filePHID' => $file_phid)); $remaining = array(); foreach ($chunks as $chunk) { if (!$chunk['complete']) { $remaining[] = $chunk; } } $done = count($chunks) - count($remaining); if ($done) { $this->writeStatus(pht('Resuming upload (%s of %s chunks remain).', phutil_count($remaining), phutil_count($chunks))); } else { $this->writeStatus(pht('Uploading chunks (%s chunks to upload).', phutil_count($remaining))); } $progress = new PhutilConsoleProgressBar(); $progress->setTotal(count($chunks)); for ($ii = 0; $ii < $done; $ii++) { $progress->update(1); } $progress->draw(); // TODO: We could do these in parallel to improve upload performance. foreach ($remaining as $chunk) { $data = $file->readBytes($chunk['byteStart'], $chunk['byteEnd']); $conduit->callMethodSynchronous('file.uploadchunk', array('filePHID' => $file_phid, 'byteStart' => $chunk['byteStart'], 'dataEncoding' => 'base64', 'data' => base64_encode($data))); $progress->update(1); } }