sironekotoroの日記

Perl で楽をしたい

Perl から Google Drive にファイルを「上書きっぽい感じ」でアップロードする

ここまで( 7 時間くらい)のあらすじ

  1. 前回の Google Drive の続きをやろう。Google Drive の特定のフォルダの配下にあるファイルを上書きアップロードしよう。

    • Google Drive は同名ファイルをフォルダ内に作成できる。
    • このため、同じファイルを続けてアップロードしても上書きにならず、同名ファイルが増えて行く。
    • f:id:sironekotoro:20201101161845p:plain
  2. 前回も使った Net::Google::Drive だと、ファイルリスト取得時にクエリーを差し挟めず、「特定のフォルダの配下にあるファイルのみ」という条件で取れない

    • 全ファイル、または名前で検索して、そのファイルの親ID(フォルダID)と照合することで特定は可能。
    • ただし、検索で引っかかったファイル数だけAPIを発行することになり遅い
  3. 他にある Perl から Google Drive を扱うモジュールを試すものの、うまくいかなくて泣く

    • Net::Google::Drive::Simple(0.18):Crypt::SSLeay のインストールがどうやってもダメ

    • WWW::Google::Drive(0.05):Google のサービスアカウント作って new してもエラーは出ないものの、SYNOPSIS 通りにメソッド呼んでも空の応答しか返ってこない

    • Google::RestApi(0.4):どうやって Google の認証情報渡せばいいかわからない〜、YAML で渡す時の key とか

  4. 諦めて Net::Google::Drive 使うか・・・うわぁ!uploadFile メソッドで file_id 指定できない!上書きできない!

    1. 名前で検索して、特定の親IDを持つファイルをリストアップ
    2. そのファイルを削除
    3. 新しいファイルをアップロード

    というのをやってみたコードが以下です。まぁ、動きだけ見れば上書きっぽい。

    終わった後だと上書きと見分けがつかない・・・いや、 file_id 変わってるか・・・

#!/usr/bin/env perl
use strict;
use warnings;

use feature qw/say/;
use Data::Dumper;
binmode STDIN,  ":utf8";
binmode STDOUT, ":utf8";

use Carp;

use Net::Google::Drive;

my $CLIENT_ID    = " ";
my $CLIENT_SECRET = " ";
my $ACCESS_TOKEN = " ";
my $REFRESH_TOKEN  = " ";

my $disk = Net::Google::Drive->new(
    -client_id     => $CLIENT_ID,
    -client_secret => $CLIENT_SECRET,
    -access_token  => $ACCESS_TOKEN,
    -refresh_token => $REFRESH_TOKEN,
);

# 更新(削除->アップロード)対象のファイル名
my $write_up_filename = 'test.txt';

# アップロード先のフォルダID
my $folder_id = '12ZOW6qR0BxDeksOuCwnWA85w4KgTh5ey';

my $files = $disk->searchFileByName( -filename => $write_up_filename, )
    or croak "File '$write_up_filename' not found";

# 特定のフォルダIDを親にしている key があり
# 特定のフォルダIDを親にもち
# ゴミ箱の中にないファイルのみを対象にする
my @metadatas = ();
for my $file ( @{$files} ) {
    my $metadata = $disk->getFileMetadata( -file_id => $file->{id}, );

    if (   exists $metadata->{parents}[0]{id}
        && $metadata->{parents}[0]{id} eq $folder_id
        && $metadata->{labels}->{trashed} == 0 )
    {
        push @metadatas, $metadata;
    }
}

# ファイル削除
for my $metadata (@metadatas) {
    $disk->deleteFile( -file_id => $metadata->{id} );
}

# ファイルアップロード
# -dest_file :アップロードしたいファイル(のパス)
# -parents   :Google Drive上のフォルダの下に格納するかを指定
my $res = $disk->uploadFile(
    -source_file => $write_up_filename,
    -parents     => [$folder_id]
    ,    # 配列リファレンスの中に指定すること
);

なお、アップロードはファイルのみ。フォルダをアップロードすることはできませんでした。

ううーん。まぁ、場合によっては使えるか・・・

追記

Net::Google::Drive::Simple なんですが、GitHub に meta::cpan よりマイナーバージョンが1上がったやつ(0.19)を発見。

これは勝てる!って思ったけどやっぱ Crypt::SSLeay への依存は変わらずでインストールできませんでした。

しょんぼり。

github.com