- Модуль: webdav
- Путь к файлу: ~/bitrix/modules/webdav/classes/editdocgoogle.php
- Класс: CWebDavEditDocGoogle
- Вызов: CWebDavEditDocGoogle::publicByResumableUpload
public function publicByResumableUpload($fileData, &$lastStatus)
{
$accessToken = $this->getAccessToken();
$convert = is_null($fileData['convert'])? true : (bool)$fileData['convert'];
$mimeType = $fileData['mimeType'];
$fileSrc = $fileData['src'];
$fileSize = $fileData['size'] = $fileData['size']? $fileData['size']: filesize($fileSrc);
$chunkSize = 40 * 256 * 1024; // Chunk size restriction: All chunks must be a multiple of 256 KB (256 x 1024 bytes) in size except for the final chunk that completes the upload
$location = $this->createFile($fileData);
if(!$location)
{
return false;
}
$lastResponseCode = false;
$finalOutput = null;
$lastRange = false;
$transactionCounter = 0;
$doExponentialBackoff = false;
$exponentialBackoffCounter = 0;
$response = array();
while ($lastResponseCode === false || $lastResponseCode == '308')
{
$transactionCounter++;
if ($doExponentialBackoff)
{
$sleepFor = pow(2, $exponentialBackoffCounter);
sleep($sleepFor);
usleep(rand(0, 1000));
$exponentialBackoffCounter++;
if ($exponentialBackoffCounter > 5)
{
$lastStatus = $response['code'];
return false;
}
}
// determining what range is next
$rangeStart = 0;
$rangeEnd = min($chunkSize, $fileSize - 1);
if ($lastRange !== false)
{
$lastRange = explode('-', $lastRange);
$rangeStart = (int)$lastRange[1] + 1;
$rangeEnd = min($rangeStart + $chunkSize, $fileSize - 1);
}
$http = new CHTTP();
$http->http_timeout = 10;
$arUrl = $http->ParseURL($location);
$http->SetAdditionalHeaders(array(
"Authorization" => "Bearer {$accessToken}",
"Content-Length" => (string)($rangeEnd - $rangeStart + 1),
"Content-Type" => $mimeType,
"Content-Range" => "bytes {$rangeStart}-{$rangeEnd}/{$fileSize}",
));
$postContentType = '';
$toSendContent = file_get_contents($fileSrc, false, null, $rangeStart, ($rangeEnd - $rangeStart + 1));
if($http->Query('PUT', $arUrl['host'], $arUrl['port'], $arUrl['path_query'], $toSendContent, $arUrl['proto'], $postContentType))
{
$response['code'] = $http->status;
$response['headers']['range'] = $http->headers['Range'];
}
$doExponentialBackoff = false;
if (isset($response['code']))
{
// checking for expired credentials
if ($response['code'] == "401")
{ // todo: make sure that we also got an invalid credential response
//$access_token = get_access_token(true);
$lastResponseCode = false;
}
else if ($response['code'] == "308")
{
$lastResponseCode = $response['code'];
$lastRange = $response['headers']['range'];
// todo: verify x-range-md5 header to be sure
$exponentialBackoffCounter = 0;
}
else if ($response['code'] == "503")
{ // Google's letting us know we should retry
$doExponentialBackoff = true;
$lastResponseCode = false;
}
else
{
if ($response['code'] == "200")
{ // we are done!
$lastResponseCode = $response['code'];
}
else
{
$lastStatus = $response['code'];
return false;
}
}
}
else
{
$doExponentialBackoff = true;
$lastResponseCode = false;
}
}
if ($lastResponseCode != "200")
{
$lastStatus = $response['code'];
return false;
}
$finalOutput = json_decode($http->result);
return array('link' => $finalOutput->alternateLink, 'id' => $finalOutput->id);
}