PHP, Guzzle, Microsoft Graph API, файловый чанк, сеанс загрузки больших файлов Не удается - как это исправить? - PullRequest
0 голосов
/ 19 октября 2019

Я пытаюсь использовать Microsoft Graph API, используя PHP для загрузки больших файлов. Согласно документации MS вы должны разбить ее на куски. Когда я использую приведенный ниже код, кажется, что он загружается до последней порции. После последней порции происходит сбой. Что именно я делаю не так и почему я получаю ошибки, указанные ниже. Нужно ли включать какую-то логику для последнего куска? или что-то еще отсутствует ...

Сведения об ошибке: PHP Неустранимая ошибка: Uncaught

1 Ответ

0 голосов
/ 23 октября 2019

Этот тип ошибки, скорее всего, возникает, поскольку последний диапазон байтов для заголовка Content-Range рассчитывается здесь неправильно:

if ($end > $fileNbByte) {
    $end = $fileNbByte;  
}

Вместо этого должно быть так:

if ($end > $fileNbByte) {
   $end = $fileNbByte + 1;
}

Это модифицированная (и более общая) версия, которая должна работать как положено:

/**
 * @param Graph $graph Graph client
 * @param string $siteId site Id
 * @param string $itemId item Id
 * @param string $inputPath input path for a file
 * @param int $chunkSize chunk size
 * @throws GraphException
 */
function uploadLargeFile($graph,$siteId,$itemId,$inputPath,$chunkSize)
{
    $fileName = basename($inputPath);
    /** @var UploadSession $uploadSession */
    $uploadSession = $graph->createRequest("POST",
        "/sites//$siteId/drive/items/$itemId:/$fileName:/createUploadSession")
        ->addHeaders(["Content-Type" => "application/json"])
        ->attachBody([
            "item" => [
                "@microsoft.graph.conflictBehavior" => "replace",
            ]
        ])
        ->setReturnType(UploadSession::class)
        ->execute();


    $handle = fopen($inputPath, 'rb');
    $fileSize = fileSize($inputPath);
    $prevBytesRead = 0;

    while (!feof($handle)) {
        $bytes = fread($handle, $chunkSize);
        $bytesRead = ftell($handle);

        $resp = $graph->createRequest("PUT", $uploadSession->getUploadUrl())
            ->addHeaders([
                'Connection' => "keep-alive",
                'Content-Length' => ($bytesRead-$prevBytesRead),
                'Content-Range' => "bytes " . $prevBytesRead . "-" . ($bytesRead-1) . "/" . $fileSize,
            ])
            ->setReturnType(UploadSession::class)
            ->attachBody($bytes)
            ->execute();

        $prevBytesRead = $bytesRead;
    }
    fclose($handle);
}

Использование

$graph = new Graph();
$token = getAccessToken($tenantId,$clientId,$clientSecret);
$graph->setAccessToken($token->access_token);
$chunkSize = 1024 * 1024;
uploadLargeFile($graph,$siteId,$itemId,$localPath,$chunkSize);
...