英文:
Laravel / Google Drive API rename folder returns 403 reason fieldNotWritable
问题
I felt optimistic when I've started investigate this issue because it looked like I wasn't the first one...
我开始调查这个问题时感到乐观,因为看起来我并不是第一个...
I have a Laravel app using Google Drive as storage. It works when I add / rename files using Storage facade.
我有一个使用Google Drive作为存储的Laravel应用程序。当我使用Storage外观添加/重命名文件时,它可以工作。
To rename a folder I'm using $googleDriveService->files->update($folder->getId(), $folder)
but I got an error 403 "The resource body includes fields which are not directly writable."
要重命名文件夹,我使用了 $googleDriveService->files->update($folder->getId(), $folder)
,但是我收到了错误403 "资源主体包含不可直接写入的字段"
On the Google OAuth 2.0 Playground I have the following scope:
- https://www.googleapis.com/auth/drive
- https://www.googleapis.com/auth/drive.file
- https://www.googleapis.com/auth/drive.metadata (I'm not sure I need this one)
在Google OAuth 2.0 Playground上,我有以下范围:
- https://www.googleapis.com/auth/drive
- https://www.googleapis.com/auth/drive.file
- https://www.googleapis.com/auth/drive.metadata (我不确定我是否需要这个)
Here is my code
$client_id = env('GOOGLE_DRIVE_CLIENT_ID');
$client_secret = env('GOOGLE_DRIVE_CLIENT_SECRET');
$refresh_token = env('GOOGLE_DRIVE_REFRESH_TOKEN');
/* Instantiate Google Client */
$googleClient = new GoogleClient();
$googleClient->setClientId($client_id);
$googleClient->setClientSecret($client_secret);
$googleClient->refreshToken($refresh_token);
$googleClient->addScope([
Google_Service_Drive::DRIVE,
Google_Service_Drive::DRIVE_FILE,
Google_Service_Drive::DRIVE_METADATA
]);
/* Instantiate Google Drive service */
$googleDriveService = new GoogleDriveService($googleClient);
function renameFolder($oldName, $newName, $path, $service)
{
/* list all folders with $oldName and select the first one matching $path */
$oldFolder = collect($service->files->listFiles(['q' => "mimeType='application/vnd.google-apps.folder' and name='$oldName'"]))
->first(fn($folder) => getFolderPath($folder->getId(), $service) === "$path/$oldName");
if(!$oldFolder) { return 'folder unknown'; }
$oldFolder->setName($newName);
/* this is the line pointed by the error */ $service->files->update($oldFolder->getId(), $oldFolder);
return compact('oldFolder');
}
function getFolderPath($folderId, $service, $delimiter = '/')
{
$path = '';
while ($folderId) {
$folder = $service->files->get($folderId, ['fields' => 'name, parents']);
if($folder->name === env('GOOGLE_DRIVE_FOLDER')) { break; }
$path = $folder->name . $delimiter . $path;
$folderId = $folder->parents;
}
return rtrim($path, $delimiter);
}
return renameFolder('old_name', 'new_name', 'path_to_folder', $googleDriveService);
When I comment the line with …->files->update(…
I see the correct folder (I compared the Id with Google Drive) and the name is the right one.
当我注释掉 …->files->update(…
这一行时,我可以看到正确的文件夹(我将其Id与Google Drive进行了比较),并且名称是正确的。
I've tried as well $googleDriveService->files->update($folder->getId(), $folder)->execute()
but I don't know what else to try… any idea is welcome.
我还尝试了 $googleDriveService->files->update($folder->getId(), $folder)->execute()
,但我不知道还可以尝试什么... 欢迎任何想法。
英文:
I felt optimistic when I've started investigate this issue because it looked like I wasn't the first one...
I have a Laravel app using Google Drive as storage. It works when I add / rename files using Storage facade.
To rename a folder I'm using $googleDriveService->files->update($folder->getId(), $folder)
but I got an error 403 "The resource body includes fields which are not directly writable."
On the Google OAuth 2.0 Playground I have the following scope:
- https://www.googleapis.com/auth/drive
- https://www.googleapis.com/auth/drive.file
- https://www.googleapis.com/auth/drive.metadata (i'm not sure I need this one)
Here is my code
$client_id = env('GOOGLE_DRIVE_CLIENT_ID');
$client_secret = env('GOOGLE_DRIVE_CLIENT_SECRET');
$refresh_token = env('GOOGLE_DRIVE_REFRESH_TOKEN');
/* Instantiate Google Client */
$googleClient = new GoogleClient();
$googleClient->setClientId($client_id);
$googleClient->setClientSecret($client_secret);
$googleClient->refreshToken($refresh_token);
$googleClient->addScope([
Google_Service_Drive::DRIVE,
Google_Service_Drive::DRIVE_FILE,
Google_Service_Drive::DRIVE_METADATA
]);
/* Instantiate Google Drive service */
$googleDriveService = new GoogleDriveService($googleClient);
function renameFolder($oldName, $newName, $path, $service)
{
/* list all folders with $oldName and select the first one matching $path */
$oldFolder = collect($service->files->listFiles(['q' => "mimeType='application/vnd.google-apps.folder' and name='$oldName'"]))
->first(fn($folder) => getFolderPath($folder->getId(), $service) === "$path/$oldName");
if(!$oldFolder) { return 'folder unknown'; }
$oldFolder->setName($newName);
/* this is the line pointed by the error */ $service->files->update($oldFolder->getId(), $oldFolder);
return compact('oldFolder');
}
function getFolderPath($folderId, $service, $delimiter = '/')
{
$path = '';
while ($folderId) {
$folder = $service->files->get($folderId, ['fields' => 'name, parents']);
if($folder->name === env('GOOGLE_DRIVE_FOLDER')) { break; }
$path = $folder->name . $delimiter . $path;
$folderId = $folder->parents;
}
return rtrim($path, $delimiter);
}
return renameFolder('old_name', 'new_name', 'path_to_folder', $googleDriveService);
When I comment the line with …->files->update(…
I see the correct folder (I compared the Id with Google Drive) and the name is the right one.
I've tried as well $googleDriveService->files->update($folder->getId(), $folder)->execute()
but I don't know what else to try… any idea is welcome
答案1
得分: 1
Thanks to Tanaike comments, I understood the problem came from
$service->files->update($oldFolder->getId(), $oldFolder);
the 2nd parameter of update method shouldn't be $oldFolder
but a new metadata object.
I've replaced
$oldFolder->setName($newName);
$service->files->update($oldFolder->getId(), $oldFolder);
by
$newMetadata = new GoogleServiceDriveDriveFile(['name' => $newName]);
$service->files->update($oldFolder->getId(), $newMetadata);
And it works.
英文:
Thanks to Tanaike comments, I understood the problem came from
$service->files->update($oldFolder->getId(), $oldFolder);
the 2nd parameter of update method shouldn't be $oldFolder
but a new metadata object.
I've replaced
$oldFolder->setName($newName);
$service->files->update($oldFolder->getId(), $oldFolder);
by
$newMetadata = new GoogleServiceDriveDriveFile(['name' => $newName]);
$service->files->update($oldFolder->getId(), $newMetadata);
And it works.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论