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

using
unset($fromFile->shared);
still leaves other writable attributes
and indeed the file is not actually shared

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

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

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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With