如何规避exportSizeLimitExceeded错误,用Google Drive API下载大文件?
解决Google Drive API导出大文件时的
exportSizeLimitExceeded错误 问题场景
通过Google Drive API的export方法下载ID为"A00001"的Google幻灯片文件,小文件可正常下载,但30MB及以上的文件会触发exportSizeLimitExceeded错误,错误信息如下:
message: This file is too large to be exported. domain: global reason: exportSizeLimitExceeded
而通过Google Drive GUI可以正常下载同文件,需要找到API端的解决方案。
原实现代码:
$fileId = 'A00001'; $outputPath = '/path/to/slide.pptx'; $response = $this->driveService->files->export($fileId, 'application/vnd.openxmlformats-officedocument.presentationml.presentation'); $body = $response->getBody(); if ($body->isSeekable()) { $body->rewind(); } $file = fopen($outputPath, 'w'); $chunkSize = 1024 * 1024; while (!$body->eof()) { $chunk = $body->read($chunkSize); fwrite($file, $chunk); } fclose($file);
解决方案
Google Drive API的直接export方法存在大小限制,而GUI的导出流程采用了不同的机制,可通过以下两种方式绕过限制:
方法一:使用可恢复导出(Resumable Export)
可恢复导出通过会话式请求流程绕过直接导出的大小限制,实现代码如下:
$fileId = 'A00001'; $outputPath = '/path/to/slide.pptx'; $mimeType = 'application/vnd.openxmlformats-officedocument.presentationml.presentation'; $chunkSize = 1024 * 1024; // 初始化可恢复导出会话 $sessionUri = $this->driveService->files->export($fileId, $mimeType, [ 'alt' => 'media', 'uploadType' => 'resumable' ]); // 创建请求对象 $request = new \Google\Http\Request('POST', $sessionUri); $mediaUpload = new \Google\Http\MediaFileUpload( $this->driveService, new \Google\Service\Drive\DriveFile(), $mimeType, null, true, $chunkSize ); // 启动会话并轮询直到导出完成 $response = $mediaUpload->initializeSession($sessionUri, $request); while ($response->getStatusCode() === 308) { sleep(5); // 间隔5秒重试,可根据实际调整 $response = $mediaUpload->resume($response); } // 写入文件到本地 $body = $response->getBody(); $file = fopen($outputPath, 'w'); while (!$body->eof()) { fwrite($file, $body->read($chunkSize)); } fclose($file);
方法二:先转换文件格式到Drive再下载
先将Google幻灯片文件复制并转换为PPTX格式保存到Drive,再下载该文件,逻辑更直观:
$fileId = 'A00001'; $outputPath = '/path/to/slide.pptx'; $targetMimeType = 'application/vnd.openxmlformats-officedocument.presentationml.presentation'; // 复制并转换文件到目标格式 $copyParams = new \Google\Service\Drive\DriveFile(); $copyParams->setName('temp_converted_slide.pptx'); // 临时文件名 $copyParams->setMimeType($targetMimeType); $convertedFile = $this->driveService->files->copy($fileId, $copyParams); // 下载转换后的文件 $downloadResponse = $this->driveService->files->get($convertedFile->getId(), [ 'alt' => 'media' ]); $body = $downloadResponse->getBody(); $file = fopen($outputPath, 'w'); while (!$body->eof()) { fwrite($file, $body->read(1024 * 1024)); } fclose($file); // 可选:删除Drive中的临时转换文件 $this->driveService->files->delete($convertedFile->getId());
方法对比
- 可恢复导出:无需在Drive中生成临时文件,节省存储空间,但需要处理轮询逻辑
- 先转换再下载:逻辑更简单,易于调试,但会在Drive中生成临时文件,可按需删除
内容的提问来源于stack exchange,提问作者Devatim
相关产品推荐
相关产品推荐

