0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Google Drive APIを使ってファイルを更新すると"fieldNotWritable"な例外が発生する

Posted at

PHPでGoogle Drive を操作するときに出くわしたエラー

やろうとしたこと

Google Drive上にすでにファイルがある場合には上書き、無い場合には更新をする

書いたコード(エラー出るバージョン)

Laravel のコマンドとして実装しているのでログがthis->infoになってますが気にしないで

Google DriveのSDKを使っています

$this->info('ファイル検索'.$fileName);

//ファイル探す
$response = $drive->files->listFiles(array(
    'q' => "mimeType='text/csv' and trashed=false and name='" . $fileName ."'",
    'spaces' => 'drive',
));

$this->info('ファイル検索'.$fileName . '/count=' . count($response->files) );

//あとで使う変数
$file = null;
$fileId = '';

//複数見つかったら、1個目を更新対象とする(とりあえずなコード)
if( count($response->files)>0 ){
    $fileId = $response->files[0]->id;
    
    //ファイルのインスタンスを抑えておく
    $file = $response->files[0];

    //ファイルを取り直しするパターンもやってみたけど意味なかった
    //$file = $drive->files->get($fileId);
}
// var_dump($file);
$this->info('ファイルID='.$fileId );

//ファイルの有無で次の動作を変える
if(!$file){
    $this->info('ファイル作成'.$fileName);
    $fileMetadata = new \Google_Service_Drive_DriveFile([
        'name' => $fileName, 
        'parents' => [$folderId], 
    ]);

    $res = $drive->files->create($fileMetadata, [
        'data' => file_get_contents(storage_path('test.csv')), 
        'mimeType' => 'text/csv',
        'uploadType' => 'media',
    ]);

    $this->info('ファイルID'.$res->id);

}else{
    $this->info('ファイル更新'.$fileName);
        
    //ファイル検索で捕まえたfileIdとFileオブジェクトを使って更新
    $res = $drive->files->update($fileId, $file, [
        'data' => file_get_contents(storage_path('newtest.csv')), 
        'mimeType' => 'text/csv',
        'uploadType' => 'media',
    ]);
}

発生するエラー

   Google\Service\Exception

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

更新できないものが混ざってるというエラーだけど、情報が少なすぎて分からず。

解決編

調べてみたけどずばりなヒントは得られず。唯一、それっぽい情報はこれ。
fileのインスタンスは作り直せよ、fileIDは除くんだぞ、というアドバイス

修正したコード(動作するバージョン)

$this->info('ファイル検索'.$fileName);

//ファイル探す
$response = $drive->files->listFiles(array(
    'q' => "mimeType='text/csv' and trashed=false and name='" . $fileName ."'",
    'spaces' => 'drive',
));

$this->info('ファイル検索'.$fileName . '/count=' . count($response->files) );

$file = null;
$fileId = '';
//複数見つかったら、1個目を更新対象とする(とりあえずなコード)
if( count($response->files)>0 ){
    $fileId = $response->files[0]->id;
    
    //ファイルのインスタンスを抑えておく
    $file = $response->files[0];
}
// var_dump($file);
$this->info('ファイルID='.$fileId );

//ファイルの有無で次の動作を変える
if(!$file){
    $this->info('ファイル作成'.$fileName);
    $fileMetadata = new \Google_Service_Drive_DriveFile([
        'name' => $fileName, 
        'parents' => [$folderId], 
    ]);

    $res = $drive->files->create($fileMetadata, [
        'data' => file_get_contents(storage_path('test.csv')), 
        'mimeType' => 'text/csv',
        'uploadType' => 'media',
    ]);

    $this->info('ファイルID'.$res->id);

}else{
    $this->info('ファイル更新'.$fileName);
    
    //ファイル検索で捕まえたFileオブジェクトではなくて、新規でインスタンスを作る
    //更新したい情報だけ入れる
    //fileIDはupdateメソッドのパラメータに入れるので、newFileのほうには入れない
    $newFile = new \Google_Service_Drive_DriveFile([
        'name' => $fileName, 
        'description'=>'desc',
    ]);
    
    $res = $drive->files->update($fileId, $newFile, [
        'data' => file_get_contents(storage_path('newtest.csv')), 
        'mimeType' => 'text/csv',
        'uploadType' => 'media',
    ]);
}

結果

うまくいきました。GitHubでコードを見つけたときは90%信じていなかったけど、やってみるものですね。

listFilesから見つかったFileオブジェクトで更新できると思ってしまったが、それがダメだった。
(というか、見つけたインスタンスを使って更新するパターンのほうが想像つきやすいと思うのだけど。。。)

Google Driveでファイルを更新するときにはSDKの気を付けてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?