Google Drive API文件监听未触发新增文件通知的原因排查
Google Drive API 共享文件夹监听问题
问题背景
为「我的云端硬盘」中的某一共享文件夹配置了Google Drive API变更通知,指定了对应文件夹的folderId,修改文件夹名称时可正常收到通知,但新增文件时无通知推送。
初始配置代码
$client = new Google_Client(); $client->setApplicationName('Some Name'); $client->setAuthConfig( __DIR__ . '/service_account.json'); $client->setScopes(Google_Service_Drive::DRIVE); $client->fetchAccessTokenWithAssertion(); $token = $client->getAccessToken(); $service = new Google\Service\Drive($client); $httpclient = new \GuzzleHttp\Client(); $folderid = $someid; $body = [ 'kind' => "api#channel", 'id' => uniqid(), 'type' => 'web_hook', 'resourceId' => $folderid, 'resourceUri' => 'https://www.googleapis.com/drive/v3/files/'.$folderid, 'address' => 'myendpoint' ]; $apiendpoint = 'https://www.googleapis.com/drive/v3/files/' . $folderid . '/watch'; $result = $httpclient->post($apiendpoint, [ 'headers' => ['Content-Type' => 'application/json', 'Authorization' => "Bearer {$token['access_token']}"], 'body' => json_encode($body), "http_errors" => false]);
配置后接口返回成功,通道立即向接收端点发送了sync消息,端点代码如下:
function myendpoint (WP_REST_Request $request) { $headers= getallheaders(); write_log('in google drive webhook with headers '.print_r($headers, true)); $body = $request->get_body(); write_log('in google drive webhook with body '.print_r($body, true)); global $wpdb; return http_response_code(200); }
日志打印的sync通知头信息如下:
[07-Nov-2021 12:52:35 UTC] in google drive webhook with headers Array ( [Host] => courses-test.com [User-Agent] => APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html) [Content-Length] => 0 [Accept] => */* [Accept-Encoding] => gzip, deflate, br [X-Forwarded-For] => 66.102.8.121 [X-Forwarded-Proto] => https [X-Goog-Channel-Expiration] => Sun, 07 Nov 2021 13:51:26 GMT [X-Goog-Channel-Id] => 6187cbc82a08e [X-Goog-Message-Number] => 1 [X-Goog-Resource-Id] => resid [X-Goog-Resource-State] => sync [X-Goog-Resource-Uri] => https://www.googleapis.com/drive/v3/files/folderid?acknowledgeAbuse=false&supportsAllDrives=false&supportsTeamDrives=false&alt=json [X-Original-Host] => mydomain )
已确认返回200状态码符合响应要求,端点响应速度正常不会触发重试机制,权限也正常,可通过listFiles接口正常列出该文件夹下的文件:
$optParams = array( 'pageSize' => 10, 'fields' => 'nextPageToken, files(id, name)' ); $results = $service->files->listFiles($optParams);
但向配置了监听的文件夹内新增、编辑文件时,均无法收到通知。该文件夹为共享文件夹,但不属于共享盘,按照官方文档说明,文件夹资源的监听应该支持add新增事件。
问题解决更新
未触发通知的原因是初始Guzzle请求错误传入了kind、resourceId(resourceId与folderId并非同一值)等多余参数,被Google服务端限制了通知推送。
修改方案为将Guzzle发起POST请求的方式替换为官方SDK的watch方法,仅传入id、address、type三个参数即可正常运行,代码如下:
$channel->setId(uniqid()); $channel->setAddress($body['address']); $channel->setType('web_hook'); $test = $service->files->watch($folderid, $channel);
修改后新增文件时,端点可收到如下请求头:
( [Host] => courses-test.com [User-Agent] => APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html) [Content-Length] => 0 [Accept] => */* [Accept-Encoding] => gzip, deflate, br [X-Forwarded-For] => someip [X-Forwarded-Proto] => https [X-Goog-Changed] => children [X-Goog-Channel-Expiration] => Mon, 08 Nov 2021 09:46:10 GMT [X-Goog-Channel-Id] => chanid [X-Goog-Message-Number] => num [X-Goog-Resource-Id] => someid [X-Goog-Resource-State] => update [X-Goog-Resource-Uri] => https://www.googleapis.com/drive/v3/files/folderid?acknowledgeAbuse=false&supportsAllDrives=false&supportsTeamDrives=false&alt=json [X-Original-Host] => mydomain )
疑问解答
1. 是否可以通过fields查询参数直接获取新增文件ID?
不可以。Google Drive API的推送通知本身返回体为空,不会携带任何变更内容,fields参数仅作用于主动调用接口时指定返回字段,无法配置到推送通知的返回内容中。
你可以在收到X-Goog-Changed: children的update事件后,调用files.list接口,使用筛选条件'[你的文件夹ID]' in parents and createdTime > [上次同步的时间戳],同时指定fields=files(id,name)即可直接拉取到新增的文件列表,不需要全量比对,效率更高。
2. 官方提到的add事件是否仅适用于Google Cloudbuckets?
情况属实。Google Drive API v3的推送通知没有add类型的X-Goog-Resource-State值,Drive的资源变更全部通过update状态配合X-Goog-Changed的不同值来区分变更类型,值为children时对应子文件/文件夹的新增、删除、移动等变更。add事件是Google Cloud Storage(GCS)的对象变更通知特有的事件类型,不适用于Google Drive API。
内容的提问来源于stack exchange,提问作者Brian
相关产品推荐
相关产品推荐

