Skip to content

Commit 89b55fe

Browse files
authored
Merge pull request #243 from nextcloud/fix/large-file-drive
fix: use alernate method to download files if export fails
2 parents e31f1a7 + 0752cb7 commit 89b55fe

1 file changed

Lines changed: 33 additions & 3 deletions

File tree

lib/Service/GoogleDriveAPIService.php

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ public function importFiles(
370370
$filePathInDrive = $dirId === 'root' ? '/' . $fileItem['name'] : $directoriesById[$dirId]['name'] . '/' . $fileItem['name'];
371371
$this->logFailedDownloadsForUser($rootImportFolder, $filePathInDrive);
372372
}
373-
} catch (\Throwable $e) {
373+
} catch (Throwable $e) {
374374
$this->logger->warning('Error while importing file', ['exception' => $e]);
375375
$this->logger->debug('Skipping file ' . strval($fileItem['id']));
376376
continue;
@@ -505,7 +505,7 @@ private function getFilesWithNameConflict(string $userId, string $dirId, bool $c
505505
* @param Folder $folder
506506
* @param string $fileName
507507
* @throws LockedException
508-
* @throws \OCP\Files\NotPermittedException
508+
* @throws NotPermittedException
509509
*/
510510
private function logFailedDownloadsForUser(Folder $folder, string $fileName): void {
511511
try {
@@ -703,7 +703,37 @@ private function getFile(string $userId, array $fileItem, Folder $saveFolder, st
703703
// potentially a doc
704704
$params = $this->getDocumentRequestParams($fileItem['mimeType'], $documentFormat);
705705
$fileUrl = 'https://www.googleapis.com/drive/v3/files/' . urlencode((string)$fileItem['id']) . '/export';
706-
return $this->downloadAndSaveFile($saveFolder, $fileName, $userId, $fileUrl, $fileItem, $params);
706+
$result = $this->downloadAndSaveFile($saveFolder, $fileName, $userId, $fileUrl, $fileItem, $params);
707+
if ($result !== null) {
708+
return $result;
709+
}
710+
$this->logger->debug('Document export failed, trying through exportLinks', ['fileItem' => $fileItem]);
711+
// Try a different method to export if that fails due to the file being too large
712+
$exportUrl = '/drive/v3/files/' . urlencode((string)$fileItem['id']);
713+
$result = $this->googleApiService->request($userId, $exportUrl, ['fields' => 'exportLinks']);
714+
if (!isset($result['exportLinks'])) {
715+
return null;
716+
}
717+
$fileUrl = null;
718+
$formatStart = $documentFormat === 'openxml' ? 'application/vnd.openxmlformats-officedocument.' : 'application/vnd.oasis.opendocument.';
719+
foreach ($result['exportLinks'] as $exportType => $potentialUrl) {
720+
if (str_starts_with($exportType, $formatStart)) {
721+
$fileUrl = $potentialUrl;
722+
break;
723+
}
724+
}
725+
// Fallback to PDF if needed
726+
if ($fileUrl === null) {
727+
if (isset($result['exportLinks']['application/pdf'])) {
728+
$this->logger->debug('Falling back to pdf', ['fileItem' => $fileItem]);
729+
$fileUrl = $result['exportLinks']['application/pdf'];
730+
} else {
731+
$this->logger->error('Could not export document', ['fileItem' => $fileItem]);
732+
return null;
733+
}
734+
}
735+
$this->logger->debug('Document export succeeded', ['fileItem' => $fileItem, 'fileUrl' => $fileUrl]);
736+
return $this->downloadAndSaveFile($saveFolder, $fileName, $userId, $fileUrl, $fileItem);
707737
} elseif (isset($fileItem['webContentLink'])) {
708738
// classic file
709739
$fileUrl = 'https://www.googleapis.com/drive/v3/files/' . urlencode((string)$fileItem['id']) . '?alt=media';

0 commit comments

Comments
 (0)