PHP - Google App Engine 将大文件作为块上传到 Google 驱动器(可恢复上传)- 500 错误

PHP - Google App Engine Uploading large files to Google Drive as chunks (Resumable Upload) - 500 Error

我正在使用后台运行的 php 代码将文件从 Google 云存储桶上传到 Google Drive 文件夹。我的问题是当文件大小增加时,Google 驱动器(或 GAE)给出 500 错误。

Error: Server Error
The server encountered an error and could not complete your request.
Please try again in 30 seconds.

我正在使用以下依赖项。

"nao-pon/flysystem-google-drive": "^1.1",

以下是出现此错误的代码部分。这非常适合小文件:

$fileN = $this->clean($att->ATT_TITLE);

$fileData = file_get_contents("https://storage.googleapis.com/xxxxxx/".$att->ATT_FILE);

$dir = sys_get_temp_dir();
$tmp = tempnam($dir, $fileN);
file_put_contents($tmp, $fileData);
Storage::cloud()->putFileAs( $folderPath, new File($tmp),$fileN);

我已经在 .env 文件中设置了配置

FILESYSTEM_CLOUD=google
GOOGLE_DRIVE_CLIENT_ID=xxxxapps.googleusercontent.com
GOOGLE_DRIVE_CLIENT_SECRET=xxxxx
GOOGLE_DRIVE_REFRESH_TOKEN=xxxxxx
GOOGLE_DRIVE_FOLDER_ID=xxxx
#GOOGLE_DRIVE_TEAM_DRIVE_ID=xxx

我在 filesystem.php

中设置了如下磁盘
'google' => [
        'driver' => 'google',
        'clientId' => env('GOOGLE_DRIVE_CLIENT_ID'),
        'clientSecret' => env('GOOGLE_DRIVE_CLIENT_SECRET'),
        'refreshToken' => env('GOOGLE_DRIVE_REFRESH_TOKEN'),
        'folderId' => env('GOOGLE_DRIVE_FOLDER_ID'),
    // 'teamDriveId' => env('GOOGLE_DRIVE_TEAM_DRIVE_ID'),
    ],

我已将 php.ini 文件设置如下

upload_max_filesize = 300M
post_max_size = 300M
memory_limit = 3000M

App.yaml

runtime: php72
handlers: 
- url: /assets
  static_dir: public/assets
env_variables:
   APP_KEY: xxxxx
   APP_STORAGE: /tmp
   CACHE_DRIVER: file
   VIEW_COMPILED_PATH: /tmp
   SESSION_DRIVER: database
   DB_DATABASE: xxx
   DB_USERNAME: xx
   DB_PASSWORD: xxxx
   DB_SOCKET: "/cloudsql/xxxxx"
runtime_config:
    document_root: public

任何人都可以给我提示或给我另一种替代方法吗?我的要求基本上是通过 Google App Engine 中的后台作业将大文件(如 250MB)上传到 Google Drive。

由于您正在调用云存储 API 上传大文件,因此可以在 60 秒内完成上传,这是 Google 云存储的默认超时 API.您可以自行修改 API 超时。这里是Whosebug case供大家参考,自己设置API超时。

对于这种情况,分块上传可以解决问题。

Refer to the following example from Google API PHP Client https://github.com/googleapis/google-api-php-client/blob/master/examples/large-file-upload.php

示例工作代码:

$fileData = file_get_contents("https://storage.googleapis.com/xxxx/".$att->ATT_FILE);

$dir = sys_get_temp_dir();
$tmp = tempnam($dir, $fileN);
file_put_contents($tmp, $fileData);       
     
$fileToUpload = new File($tmp);
$filename = $fileN;
$mimeType = mime_content_type($tmp);
                   
$driveService = Storage::cloud();
$client = new \Google_Client();
$client->setClientId('xxxx');
$client->setClientSecret('xxx');
$client->refreshToken('xxx');
$client->setApplicationName('xxx');

$service = new \Google_Service_Drive($client);


// Test 1
$file = new \Google_Service_Drive_DriveFile();
$file->title = $fileN;
$file->name = $fileN;
$file->parents = array($basePath);
$chunkSizeBytes = 1 * 1024 * 1024;

// Call the API with the media upload, defer so it doesn't immediately return.
$client->setDefer(true);
$request = $service->files->create($file);

// Create a media file upload to represent our upload process.
$media = new \Google_Http_MediaFileUpload(
  $client,
  $request,
  $mimeType,
  null,
  true,
  $chunkSizeBytes
);
$media->setFileSize(filesize($tmp));

// Upload the various chunks. $status will be false until the process is
// complete.
$status = false;
$handle = fopen($tmp, "rb");
while (!$status && !feof($handle)) {
  $chunk = fread($handle, $chunkSizeBytes);
  $status = $media->nextChunk($chunk);
 }

// The final value of $status will be the data from the API for the object
// that has been uploaded.
$result = false;
if($status != false) {
  $result = $status;
}

fclose($handle);