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:
GoogleServiceException
{ "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

File Move Google Drive API v3 PHP

using

unset($fromFile->shared);

still leaves other writable attributes

and indeed the file is not actually shared

File Move Google Drive API v3 PHP


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
File Move Google Drive API v3 PHP

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

File Move Google Drive API v3 PHP

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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 fileds *

 $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 soultion 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.

Method 2

I don’t know how to do in laravel but the problem might be

I have also faced the same problem some time and after searching internet for over months found nothing and one day Referring to documentation, seen that shared
isn’t a writable field.

That’s it, if you are sharing the File and trying to move the file it wouldn’t move. Try to un-share the File and then try to move the File it would be done.

Method 3

I ended up creating a custom function to only include writeable attributes as specified in the Google Documentation:

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

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


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x