Edit File: ChunkFileUploader.inc
<?php /** * Author: Shlomi * Date: Sep 6, 2017 4:12:49 PM * Founder: Shlomi Bazak (SBZsoft) (c) * File: ChunkFileUploader.inc * * Description: * */ namespace B2\Entities; use B2\FS\FileReader; use B2\Http\B2Client; use B2\Exceptions\B2Exception; use B2\Exceptions\UploadFailedException; // No direct access. defined("__NSS__") or die("Restrected Access."); class ChunkFileUploader { private $_client, $_reader, $_bucketId, $_chunkSize, $_path, $_retries; protected $_fileId, $_uploadUrl, $_authToken; protected $_parts, $_hashes, $_currentChunk; /** * Initialize a new ChunkFileUploader. * @param B2Client $client B2client connected to BackBlaze. * @param FileReader $reader FileReader with reference to the file to read from. * @param Bucket $bucket The bucket to upload to. * @param string $path The path on the Bucket to upload to. * @param int $retries if upload fails, retry this number of times. */ public function __construct(B2Client $client, FileReader $reader, Bucket $bucket, $path, $retries){ $this->_client = $client; $this->_bucketId = $bucket->getId(); $this->_reader = $reader; $this->_path = $path; $this->_retries = $retries>0?$retries:0; } protected function startUpload(){ $params = [ 'bucketId' => $this->_bucketId, 'fileName' => $this->_path, 'contentType' => $this->_reader->getConetnType(), 'fileInfo' => ['src_last_modified_millis' => "".($this->_reader->getModificationTime()*1000) ] ]; $data = $this->_client->requestApi(B2Api::START_LARGE_FILE, $params); $this->_fileId = $data['fileId']; } protected function getUploadPartUrl(){ $params = [ 'fileId' => $this->_fileId ]; $data = $this->_client->requestApi(B2Api::GET_UPLOAD_PART_URL, $params); $this->_uploadUrl = $data['uploadUrl']; $this->_authToken = $data['authorizationToken']; } protected function uploadPart(){ $headers = [ 'Authorization' => $this->_authToken, 'X-Bz-Part-Number' => $this->_parts, 'Content-Length' => $this->_currentChunk->getSize(), 'X-Bz-Content-Sha1' => $this->_currentChunk->getHash() ]; $send_data = [ 'headers' => $headers, 'body' => $this->_currentChunk->getData() ]; //try { $data = $this->_client->_requestJson(B2Client::METHOD_POST, $this->_uploadUrl, $send_data); } //catch(B2Exception $e){ return false; } $data = $this->_client->_requestJson(B2Client::METHOD_POST, $this->_uploadUrl, $send_data); return $data["contentLength"] == $this->_currentChunk->getSize() && $data['contentSha1'] == $this->_currentChunk->getHash() && $data['fileId'] == $this->_fileId && $data['partNumber'] == $this->_parts; } protected function uploadParts(){ $this->_parts = 1; $this->_hashes = []; $this->_reader->rewind(); while(($this->_currentChunk = $this->_reader->getNextChunkStream())) { $errs = 0; $success=false; $lastEx=null; while(!$success && $errs <= $this->_retries){ try { $this->uploadPart(); $success=true; }catch(\Exception $e){ $lastEx = $e; $this->getUploadPartUrl(); $errs++; } } if(!$success){ if($lastEx) throw $lastEx; throw new UploadFailedException("Upload failed for {$this->_reader->getName()}."); } $this->_hashes[] = $this->_currentChunk->getHash(); $this->_parts++; } } protected function fanalizeUpload(){ $params = [ 'fileId' => $this->_fileId, 'partSha1Array' => $this->_hashes ]; $data = $this->_client->requestApi(B2Api::FINISH_LARGE_FILE, $params); return new File($data); } /** * Start chunked upload process * @throws UploadFailedException if upload was unsuccessful. * @throws B2Exception if reading or writing ware unsuccessful. * @return \B2\Entities\File uploaded file data. */ public function upload(){ $this->startUpload(); $this->getUploadPartUrl(); $this->uploadParts(); return $this->fanalizeUpload(); } }