文件移动 Google Drive API v3 PHP

Posted

技术标签:

【中文标题】文件移动 Google Drive API v3 PHP【英文标题】:File Move Google Drive API v3 PHP 【发布时间】:2021-11-09 22:04:03 【问题描述】:

使用 Google API v3 我尝试将文件从一个文件夹移动到另一个文件夹。我在 Laravel 中使用包装类,文件和父 ID 是正确的。从文档开发,我尝试了以下代码:

public function moveFileFromTo($fileID, $toParentID) 
    $fromFile = $this->service->files->get($fileID, ['fields' => '*']);
    $fromParentID = $fromFile->getParents();
    $blankFile = new Google_Service_Drive_DriveFile();
    $this->service->files->update($fileID, $blankFile, [
        "removeParents" => $fromParentID,
        "addParents" => $toParentID
    ]);

但是,这似乎会移动文件,但会删除所有元数据。 我也试过了

public function moveFileFromTo($fileID, $toParentID) 
    $fromFile = $this->service->files->get($fileID, ['fields' => '*']);
    $fromParentID = $fromFile->getParents();
    $fromFile->setParents($fromParentID);
    $this->service->files->update($fileID, $fromFile);

但是,这会产生错误:

Google\Service\Exception
 "error":  "errors": [  "domain": "global", "reason": 
"fieldNotWritable", "message": "The resource body includes fields 
which are not directly writable."  ], "code": 403, "message": "The 
resource body includes fields which are not directly writable."  

我希望简单地移动文件并保留其所有元数据。从文档中,似乎更新中需要一个新的空文件(真的很奇怪),或者我必须以某种方式删除它不喜欢写入的第二个参数($fromFile)中使用的对象的字段(即使我只是在更新父母的文件——这是可写的)。

另见https://issuetracker.google.com/issues/199921300


到目前为止的答案问题: 但感谢回复

$fromFile = $this->service->files->get($fileID, ['fields' => 'parents, id']);

返回所有 ~75 个属性,其中很多是不可写的。 而不是根据 phpStorm 调试预期的 2(请注意,中断位于 GET 请求之后的语句中,因此此时无关紧要

使用

unset($fromFile->shared);

仍然保留其他可写属性

确实该文件实际上并未共享


更新我的编码

public function moveFileFromTo($fileID, $toParentID) 
    $fromFile = $this->service->files->get($fileID, ["fields" => "id,parents"]);
    $fromFile = $this->getParsedWritableFile($fromFile);
    $fromFile->setParents($toParentID);
    $this->service->files->update($fileID, $fromFile, ['addParents' => $toParentID]);

getParsedWritableFile 正在尝试在新的 Google Drive 文件对象上设置可写属性:

public function getParsedWritableFile($gdrivefile) 
        $gdrivefile = new \Google_Service_Drive_DriveFile();//comment or delete, just here to check auto complete function names

        $parsedFile = new \Google_Service_Drive_DriveFile();
        //$parsedFile=$gdrivefile;
        // currently only allow these according to https://developers.google.com/drive/api/v3/reference/files#resource-representations
        $parsedFile->setName($gdrivefile->getName());//name
        $parsedFile->setMimeType($gdrivefile->getMimeType());//mimeType
        $parsedFile->setDescription($gdrivefile->getDescription());//description
        $parsedFile->setStarred($gdrivefile->getStarred());//starred
        $parsedFile->setTrashed($gdrivefile->getTrashed());//trashed
        $parsedFile->setParents($gdrivefile->getParents());//parents
        $parsedFile->setProperties($gdrivefile->getProperties());//properties  [object]
        $parsedFile->setAppProperties($gdrivefile->getAppProperties());//appProperties [object]
        $parsedFile->setCreatedTime($gdrivefile->getCreatedTime());//createdTime
        $parsedFile->setModifiedTime($gdrivefile->getModifiedTime());//modifiedTime
        $parsedFile->setWritersCanShare($gdrivefile->getWritersCanShare());//writersCanShare
        $parsedFile->setViewedByMeTime($gdrivefile->getViewedByMeTime());//viewedByMeTime
        $parsedFile->setFolderColorRgb($gdrivefile->getFolderColorRgb());//folderColorRgb
        $parsedFile->setOriginalFilename($gdrivefile->getOriginalFilename());//originalFilename
        $parsedFile->setCopyRequiresWriterPermission($gdrivefile->getCopyRequiresWriterPermission());//copyRequiresWriterPermission

        /*complex permissions*/
        /*
        contentHints.thumbnail.image
        contentHints.thumbnail.mimeType
        contentHints.indexableText
         */
        $contenthints=$gdrivefile->getContentHints();//could be null meaning further functions eg getThumbnail cause exception
        if($contenthints)
            $parsedFile->setContentHints($contenthints->getThumbnail()->getImage());
            $parsedFile->setContentHints($contenthints->getThumbnail()->getMimeType());
            $parsedFile->setContentHints($contenthints->getIndexableText());
        

        /*no function to get indiviual attributes*/
        /*
contentRestrictions[].readOnly
ccontentRestrictions[].reason
         */
        $parsedFile->setContentRestrictions($gdrivefile->getContentRestrictions());

        //</ end>
        return $parsedFile;
    

这证明有点成功,但这是原始元数据

上面的代码确实移动了它,看似正确的元数据、创建时间和 EXIF 数据现在完好无损

【问题讨论】:

看起来有更多人遇到同样的问题。 ***.com/q/48891303/1702206laravelquestions.com/2021/09/14/… 您可能想尝试将文件复制到新位置,然后从原始位置删除文件。这可能会保留元数据。 @ajt 好像那个网站刚刚在复制 *** !!!问题是逐字逐句 @Datadimension word for word o.0 yup copying *** 【参考方案1】:

问题是您使用的是file.update,它使用HTTP PATCH 方法。通过使用 PATCH,它会尝试更新您发送的文件对象中的所有属性。

你做了一个 file.get 并且你包含了文件 *

 $fromFile = $this->service->files->get($fileID, ['fields' => '*']);

通过包含'fields' =&gt; '*',您告诉API 将文件具有的所有属性返回给您。一个file resource 有很多属性,而且它们都不是可写的。

通过向 file.update 方法发送您告诉它您想要更新所有内容的所有字段,包括一些您不允许更新的属性。 api 以 fieldNotWritable 响应的对象

建议做以下事情

$fromFile = $this->service->files->get($fileID, ['fields' => 'parents, id']);

这将导致该方法仅返回您实际需要的两个参数。 id 和 parents 参数。 (TBH 你可能只需要父母部分,我需要测试一下。)


 "id": "1x8-vD-XiA5Spf3qp8x2wltablGF22Lpwup8VtxNY",
 "parents": ["0B1bbSFgVLpoXcVDRFRF8tTkU"
 ]

然后您应该被允许更新父级并移动您的文件。

【讨论】:

这仍然返回所有 75 个属性(这是一个错误吗?) ['fields' => 'parents, id'] 应该只返回这两个属性。 @DalmTo - 感谢您的回复,但如上面的编辑问题所示,它没有。请询问您需要的任何信息,并感谢迄今为止的回复 对我来说听起来像是一个工作案例,因为我刚刚再次测试它并且它可以工作文件。 感谢您的测试,但这里没有您使用的 API 版本,(此处为 php 7.4.13 上的 v2.10.1)【参考方案2】:

我不知道如何在 laravel 中做,但问题可能是

我也遇到过同样的问题,在网上搜索了几个月后,一无所获,一天参考documentation,看到shared 不是可写字段。

就是这样,如果您正在共享文件并尝试移动文件,它就不会移动。尝试取消共享文件,然后尝试移动文件即可。

【讨论】:

有很多字段不可写。我不想手动编写代码来剥离它们,以防谷歌改变主意或添加其他字段,这会破坏代码 @Datadimension 它只有一个简单的逻辑,如果共享文档,则无法移动文档,要么删除它,要么取消共享以移动文档。您不必检查其他字段。 谢谢,但目的是使用编码 API。简单的逻辑在这里是不正确的,因为文件不是按照谷歌 GUI 共享的,我使用 API 取消设置了这个属性,并且仍然出现同样的错误【参考方案3】:

我最终创建了一个自定义函数,仅包含 Google 文档中指定的可写属性:

public function getParsedWritableFile($gdrivefile) 
        $gdrivefile = new \Google_Service_Drive_DriveFile();//comment or delete, just here to check auto complete function names
        $parsedFile = new \Google_Service_Drive_DriveFile();

        // currently only allow these according to https://developers.google.com/drive/api/v3/reference/files#resource-representations
        $parsedFile->setName($gdrivefile->getName());//name
        $parsedFile->setMimeType($gdrivefile->getMimeType());//mimeType
        $parsedFile->setDescription($gdrivefile->getDescription());//description
        $parsedFile->setStarred($gdrivefile->getStarred());//starred
        $parsedFile->setTrashed($gdrivefile->getTrashed());//trashed
        $parsedFile->setParents($gdrivefile->getParents());//parents
        $parsedFile->setProperties($gdrivefile->getProperties());//properties  [object]
        $parsedFile->setAppProperties($gdrivefile->getAppProperties());//appProperties [object]
        $parsedFile->setCreatedTime($gdrivefile->getCreatedTime());//createdTime
        $parsedFile->setModifiedTime($gdrivefile->getModifiedTime());//modifiedTime
        $parsedFile->setWritersCanShare($gdrivefile->getWritersCanShare());//writersCanShare
        $parsedFile->setViewedByMeTime($gdrivefile->getViewedByMeTime());//viewedByMeTime
        $parsedFile->setFolderColorRgb($gdrivefile->getFolderColorRgb());//folderColorRgb
        $parsedFile->setOriginalFilename($gdrivefile->getOriginalFilename());//originalFilename
        $parsedFile->setCopyRequiresWriterPermission($gdrivefile->getCopyRequiresWriterPermission());//copyRequiresWriterPermission

        /*complex permissions*/
        /*
        contentHints.thumbnail.image
        contentHints.thumbnail.mimeType
        contentHints.indexableText
         */
        $contenthints=$gdrivefile->getContentHints();//could be null meaning further functions eg getThumbnail cause exception
        if($contenthints)
            $parsedFile->setContentHints($contenthints->getThumbnail()->getImage());
            $parsedFile->setContentHints($contenthints->getThumbnail()->getMimeType());
            $parsedFile->setContentHints($contenthints->getIndexableText());
        

        /*no function to get indiviual attributes*/
        /*
contentRestrictions[].readOnly
ccontentRestrictions[].reason
         */
        $parsedFile->setContentRestrictions($gdrivefile->getContentRestrictions());
        return $parsedFile;
    

并调用

public function moveFileFromTo($fileID, $toParentID) 
    $fromFile = $this->service->files->get($fileID, ["fields" => "id,parents"]);
    $fromFile = $this->getParsedWritableFile($fromFile);
    $fromFile->setParents($toParentID);
    $this->service->files->update($fileID, $fromFile, ['addParents' => $toParentID]);

【讨论】:

以上是关于文件移动 Google Drive API v3 PHP的主要内容,如果未能解决你的问题,请参考以下文章

Google Drive API v3 Python文件中缺少某些文件()。list()

Javascript - Google Drive v3 API和功能

如何从 Google Drive 上传和下载文件(使用 Rest Api v3)

如何通过 Google Drive .NET API v3 使用服务帐户访问 Team Drive

如何在使用Google Drive API V3与他人共享时设置文件的功能?

Google Drive API v3-将文档转换为pdf