nao-pon / flysystem-google-drive

Flysystem adapter for Google Drive
MIT License
352 stars 128 forks source link

Fix upload file Google_Service_Exception #80

Closed underthecocotree closed 4 years ago

underthecocotree commented 4 years ago

Related to: https://github.com/nao-pon/flysystem-google-drive/issues/78

After thorough debugging with xdebug and a proxy I have found the following.

When uploading a file it seems that the code is checking whether that file exists.

Flysystem tries to see if it will write or update the stream public function Filesystem::putStream($path, $resource, array $config = []) bool

If I am not mistaken, the file gets created and then the data gets uploaded. When using batch and we check whether the file exists the API sends back a 200 Response with a 404 error within - that allows the code execution to continue. On the contrary with 2bf6a49 when we try to use the same code we get a 404 Response and the application throws a Google_Service_Exception exception

While in the batch the code will continue to execute. In the 2bf6a49, the exception stops any subsequent requests to upload the file.

One of the Batch Requests

POST https://www.googleapis.com/batch/drive/v3 HTTP/1.1
Host: www.googleapis.com
...
GET /drive/v3/files/filename.pptx?fields=id%2Cname%2CmimeType%2CmodifiedTime%2Cparents%2Cpermissions%2Csize%2CwebContentLink%2CwebViewLink HTTP/1.1
...

200 Response with a 404 inside

HTTP/1.1 200 OK
...

29a
--batch_xxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/http
Content-ID: response-obj

HTTP/1.1 404 Not Found
...

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "notFound",
    "message": "File not found: filename.pptx.",
    "locationType": "parameter",
    "location": "fileId"
   }
  ],
  "code": 404,
  "message": "File not found: filename.pptx."
 }
}

--batch_yyyyyyyyyyyyyyyyyyyyyyyy-

2bf6a49 Request returns 404 and not 200, application throws a Google_Service_Exception

GET https://www.googleapis.com/drive/v3/files/filename.pptx?fields=id%2Cname%2CmimeType%2CmodifiedTime%2Cparents%2Cpermissions%2Csize%2CwebContentLink%2CwebViewLink HTTP/1.1
...

# 404 Response
HTTP/1.1 404 Not Found

14a
{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "notFound",
    "message": "File not found: filename.pptx.",
    "locationType": "parameter",
    "location": "fileId"
   }
  ],
  "code": 404,
  "message": "File not found: filename.pptx."
 }
}

Fix

Wrapping these lines in a try catch block seems to work. This allows for the file upload to work. Let me know if this is not the ideal solution.

try {
  $results[] = $this->service->files->get($itemId, $this->applyDefaultParams($opts, 'files.get'));

  if ($checkDir && $this->useHasDir) {
    $results[] = $service->files->listFiles($this->applyDefaultParams([
      'pageSize' => 1,
      'q' => sprintf('trashed = false and "%s" in parents and mimeType = "%s"', $itemId, self::DIRMIME)
    ], 'files.list'));
  }
}
catch (\Google_Service_Exception $e){
  // Do nothing or something but deal with the Exception and continue
  return NULL; // skips the code below which would return NULL anyway
}
nao-pon commented 4 years ago

@underthecocotree I think this is good. Thank you! 👍