Laravel / Google Drive API 重命名文件夹返回 403 错误,原因字段为 fieldNotWritable。

huangapple go评论68阅读模式
英文:

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:

在Google OAuth 2.0 Playground上,我有以下范围:

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:

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.

huangapple
  • 本文由 发表于 2023年6月15日 05:32:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76477690.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定