protected function upload_file(\repository_onedrive\rest $service, \curl $curl, \curl $authcurl,
                                   $filepath, $mimetype, $parentid, $filename) {
        // Start an upload session.
        // Docs https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/item_createuploadsession link.

        $params = ['parentid' => $parentid, 'filename' => urlencode($filename)];
        $behaviour = [ 'item' => [ "@microsoft.graph.conflictBehavior" => "rename" ] ];
        $created = $service->call('create_upload', $params, json_encode($behaviour));
        if (empty($created->uploadUrl)) {
            $details = 'Cannot begin upload session:' . $parentid;
            throw new repository_exception('errorwhilecommunicatingwith', 'repository', '', $details);
        }

        $options = ['file' => $filepath];

        // Try each curl class in turn until we succeed.
        // First attempt an upload with no auth headers (will work for personal onedrive accounts).
        // If that fails, try an upload with the auth headers (will work for work onedrive accounts).
        $curls = [$curl, $authcurl];
        $response = null;
        foreach ($curls as $curlinstance) {
            $curlinstance->setHeader('Content-type: ' . $mimetype);
            $size = filesize($filepath);
            $curlinstance->setHeader('Content-Range: bytes 0-' . ($size - 1) . '/' . $size);
            $response = $curlinstance->put($created->uploadUrl, $options);
            if ($curlinstance->errno == 0) {
                $response = json_decode($response);
            }
            if (!empty($response->id)) {
                // We can stop now - there is a valid file returned.
                break;
            }
        }

        if (empty($response->id)) {
            $details = 'File not created';
            throw new repository_exception('errorwhilecommunicatingwith', 'repository', '', $details);
        }

        return $response->id;
    }