lib/Dropbox/Client.php
private function _uploadFileChunked($path, $writeMode, $inStream, $numBytes, $chunkSize)
    {
        Path::checkArg("path", $path);
        WriteMode::checkArg("writeMode", $writeMode);
        Checker::argResource("inStream", $inStream);
        Checker::argNatOrNull("numBytes", $numBytes);
        Checker::argNat("chunkSize", $chunkSize);

        // NOTE: This function performs 3 retries on every call.  This is maybe not the right
        // layer to make retry decisions.  It's also awkward because none of the other calls
        // perform retries.

        assert($chunkSize > 0);

        $data = self::readFully($inStream, $chunkSize);
        $len = strlen($data);

        $client = $this;
        $uploadId = RequestUtil::runWithRetry(3, function() use ($data, $client) {
            return $client->chunkedUploadStart($data);
        });

        $byteOffset = $len;

        while (!feof($inStream)) {
            $data = self::readFully($inStream, $chunkSize);
            $len = strlen($data);

            while (true) {
                $r = RequestUtil::runWithRetry(3,
                    function() use ($client, $uploadId, $byteOffset, $data) {
                        return $client->chunkedUploadContinue($uploadId, $byteOffset, $data);
                    });

                if ($r === true) {  // Chunk got uploaded!
                    $byteOffset += $len;
                    break;
                }
                if ($r === false) {  // Server didn't recognize our upload ID
                    // This is very unlikely since we're uploading all the chunks in sequence.
                    throw new Exception_BadResponse("Server forgot our uploadId");
                }

                // Otherwise, the server is at a different byte offset from us.
                $serverByteOffset = $r;
                assert($serverByteOffset !== $byteOffset);  // chunkedUploadContinue ensures this.
                // An earlier byte offset means the server has lost data we sent earlier.
                if ($serverByteOffset < $byteOffset) throw new Exception_BadResponse(
                    "Server is at an ealier byte offset: us=$byteOffset, server=$serverByteOffset");
                $diff = $serverByteOffset - $byteOffset;
                // If the server is past where we think it could possibly be, something went wrong.
                if ($diff > $len) throw new Exception_BadResponse(
                    "Server is more than a chunk ahead: us=$byteOffset, server=$serverByteOffset");
                // The normal case is that the server is a bit further along than us because of a
                // partially-uploaded chunk.  Finish it off.
                $byteOffset += $diff;
                if ($diff === $len) break;  // If the server is at the end, we're done.
                $data = substr($data, $diff);
            }
        }

        if ($numBytes !== null && $byteOffset !== $numBytes) throw new \InvalidArgumentException(
            "You passed numBytes=$numBytes but the stream had $byteOffset bytes.");

        $metadata = RequestUtil::runWithRetry(3,
            function() use ($client, $uploadId, $path, $writeMode) {
                return $client->chunkedUploadFinish($uploadId, $path, $writeMode);
            });

        return $metadata;
    }
private function _uploadFileChunked($path, $writeMode, $inStream, $numBytes, $chunkSize)
    {
        Path::checkArg("path", $path);
        WriteMode::checkArg("writeMode", $writeMode);
        Checker::argResource("inStream", $inStream);
        Checker::argNatOrNull("numBytes", $numBytes);
        Checker::argNat("chunkSize", $chunkSize);

        // NOTE: This function performs 3 retries on every call.  This is maybe not the right
        // layer to make retry decisions.  It's also awkward because none of the other calls
        // perform retries.

        assert($chunkSize > 0);

        $data = self::readFully($inStream, $chunkSize);
        $len = strlen($data);

        $client = $this;
        $uploadId = RequestUtil::runWithRetry(3, function() use ($data, $client) {
            return $client->chunkedUploadStart($data);
        });

        $byteOffset = $len;

        while (!feof($inStream)) {
            $data = self::readFully($inStream, $chunkSize);
            $len = strlen($data);

            while (true) {
                $r = RequestUtil::runWithRetry(3,
                    function() use ($client, $uploadId, $byteOffset, $data) {
                        return $client->chunkedUploadContinue($uploadId, $byteOffset, $data);
                    });

                if ($r === true) {  // Chunk got uploaded!
                    $byteOffset += $len;
                    break;
                }
                if ($r === false) {  // Server didn't recognize our upload ID
                    // This is very unlikely since we're uploading all the chunks in sequence.
                    throw new Exception_BadResponse("Server forgot our uploadId");
                }

                // Otherwise, the server is at a different byte offset from us.
                $serverByteOffset = $r;
                assert($serverByteOffset !== $byteOffset);  // chunkedUploadContinue ensures this.
                // An earlier byte offset means the server has lost data we sent earlier.
                if ($serverByteOffset < $byteOffset) throw new Exception_BadResponse(
                    "Server is at an ealier byte offset: us=$byteOffset, server=$serverByteOffset");
                $diff = $serverByteOffset - $byteOffset;
                // If the server is past where we think it could possibly be, something went wrong.
                if ($diff > $len) throw new Exception_BadResponse(
                    "Server is more than a chunk ahead: us=$byteOffset, server=$serverByteOffset");
                // The normal case is that the server is a bit further along than us because of a
                // partially-uploaded chunk.  Finish it off.
                $byteOffset += $diff;
                if ($diff === $len) break;  // If the server is at the end, we're done.
                $data = substr($data, $diff);
            }
        }

        if ($numBytes !== null && $byteOffset !== $numBytes) throw new \InvalidArgumentException(
            "You passed numBytes=$numBytes but the stream had $byteOffset bytes.");

        $metadata = RequestUtil::runWithRetry(3,
            function() use ($client, $uploadId, $path, $writeMode) {
                return $client->chunkedUploadFinish($uploadId, $path, $writeMode);
            });

        return $metadata;
    }
private function _uploadFileChunked ( $ path , $ writeMode , $ inStream , $ numBytes , $ chunkSize ) { Path :: checkArg ( "path" , $ path ) ; WriteMode :: checkArg ( "writeMode" , $ writeMode ) ; Checker :: argResource ( "inStream" , $ inStream ) ; Checker :: argNatOrNull ( "numBytes" , $ numBytes ) ; Checker :: argNat ( "chunkSize" , $ chunkSize ) ; // NOTE: This function performs 3 retries on every call.  This is maybe not the right // layer to make retry decisions.  It's also awkward because none of the other calls // perform retries. assert ( $ chunkSize > 0 ) ; $ data = self :: readFully ( $ inStream , $ chunkSize ) ; $ len = strlen ( $ data ) ; $ client = $ this ; $ uploadId = RequestUtil :: runWithRetry ( 3 , function ( ) use ( $ data , $ client ) { return $ client -> chunkedUploadStart ( $ data ) ; } ) ; $ byteOffset = $ len ; while ( ! feof ( $ inStream ) ) { $ data = self :: readFully ( $ inStream , $ chunkSize ) ; $ len = strlen ( $ data ) ; while ( true ) { $ r = RequestUtil :: runWithRetry ( 3 , function ( ) use ( $ client , $ uploadId , $ byteOffset , $ data ) { return $ client -> chunkedUploadContinue ( $ uploadId , $ byteOffset , $ data ) ; } ) ; if ( $ r === true ) { // Chunk got uploaded! $ byteOffset += $ len ; break ; } if ( $ r === false ) { // Server didn't recognize our upload ID // This is very unlikely since we're uploading all the chunks in sequence. throw new Exception_BadResponse ( "Server forgot our uploadId" ) ; } // Otherwise, the server is at a different byte offset from us. $ serverByteOffset = $ r ; assert ( $ serverByteOffset !== $ byteOffset ) ; // chunkedUploadContinue ensures this. // An earlier byte offset means the server has lost data we sent earlier. if ( $ serverByteOffset < $ byteOffset ) throw new Exception_BadResponse ( "Server is at an ealier byte offset: us=$byteOffset, server=$serverByteOffset" ) ; $ diff = $ serverByteOffset - $ byteOffset ; // If the server is past where we think it could possibly be, something went wrong. if ( $ diff > $ len ) throw new Exception_BadResponse ( "Server is more than a chunk ahead: us=$byteOffset, server=$serverByteOffset" ) ; // The normal case is that the server is a bit further along than us because of a // partially-uploaded chunk.  Finish it off. $ byteOffset += $ diff ; if ( $ diff === $ len ) break ; // If the server is at the end, we're done. $ data = substr ( $ data , $ diff ) ; } } if ( $ numBytes !== null && $ byteOffset !== $ numBytes ) throw new \ InvalidArgumentException ( "You passed numBytes=$numBytes but the stream had $byteOffset bytes." ) ; $ metadata = RequestUtil :: runWithRetry ( 3 , function ( ) use ( $ client , $ uploadId , $ path , $ writeMode ) { return $ client -> chunkedUploadFinish ( $ uploadId , $ path , $ writeMode ) ; } ) ; return $ metadata ; }
@param string $path

@param WriteMode $writeMode
What to do if there's already a file at the given path (UTF-8).

@param resource $inStream
The source of data to upload.

@param int|null $numBytes
You can pass in `null`.  But if you know how many bytes you expect, pass in
that value and this function will do a sanity check at the end to make sure the number of
bytes read from `$inStream` matches up.

@param int $chunkSize

@return array
The <a href="https://www.dropbox.com/developers/core/docs#metadata-details>metadata
object</a> for the newly-added file.
@param string $path