Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

File Move Google Drive API v3 PHP

Using Google API v3 I try to move a file from one folder to another. I am using a wrapper class in Laravel, the file and parent IDs are correct. Developing from the documentation, I have tried code as:

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
    ]);
}

However, this seems to move the file but strips out all the meta data. I have also tried

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

However, this gives the error:

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." } }

I wish to simply move the file and retain all its metadata. From the documentation, it seems either a new empty file is required in update (really weird) or I must somehow strip out the fields of the object used in the second argument ($fromFile) it does not like to be written to (even though I am simply updating the files parents - which is writable).

See also https://issuetracker.google.com/issues/199921300


Problems with Answers so far: but grateful for responses

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

returns all ~75 attributes a lot of which are not writeable. Instead of the expected 2 as per PHPStorm debug (note the break is at the statement immediately following the GET request so irrelevant at this point

enter image description here

using

unset($fromFile->shared);

still leaves other writable attributes

and indeed the file is not actually shared

enter image description here


UPDATE TO MY CODING

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 is trying to just set writable attributes on a new Google Drive file object:

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;
    }

This is proving a bit successful but this is original meta enter image description here

the above code does move it, with seemingly proper meta data, created time and EXIF data is now intact

enter image description here

like image 331
Datadimension Avatar asked Jul 01 '26 21:07

Datadimension


1 Answers

The problem is that you are using file.update which uses HTTP PATCH methodology. By using a PATCH its going to try to update all of the properties in the file object that you send.

You did a file.get and you included fields *

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

By including 'fields' => '*' you told the API to return to you all of the properties that the file has. A file resource has a lot of properties and they are not all writeable.

By sending the file.update method all of the fields you are telling it you want to update everything including some of the properties that you are not allowed to update. To which the api responds with fieldNotWritable

The solution would be to do the following

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

Which will cause the method to only return the two parameters that you actual need. The id and the parents parameter. (TBH you may just need the parents part, I would need to test that.)

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

You should then be allowed to update the parent and move your file.

like image 167
DaImTo Avatar answered Jul 03 '26 11:07

DaImTo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!