この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
CX事業本部の中安です。本日は小ネタです。
AWS SDK for PHP
(現環境:v.3.91.5) を使用してS3上のオブジェクトをある場所からある場所にPHP側から移動させようとしました。
が、しかし、うまく行かずに結局かなりの時間がかかってしまいました。
PHPのAWSSDKでS3のオブジェクトをリネームしたく、コピーしてコピー元を削除するということをしたいのだが、コピーは成功して削除がうまくいってなくて、ファイルが意図せず2つになる
凡ミスなのか、そもそもやり方マズってるのか、、掴めないまま帰宅— めそめそなくやす (@nkysyuichi) November 6, 2019
↑悩んでる際のわたくし
cliだといけるんですか?
— かずえ (@kazueeee_) November 6, 2019
S3の結果整合性とか・・・すいません、雑で。
— SIN.Hirauchi/クラスメソッド (@furuya02) November 6, 2019
↑よくわからないことを呟いてるところを駆けつけてくれるクラメソの仲間たち
まぁ、でもわかってみると「なーんだ」という内容でして、結局凡ミスではありました。 自戒の念も込めてブログにしたためておきます。
どうなってたのか
最初のツイッターに書いてあることなのですが、整理して申し上げると
- 僕は、S3上のオブジェクトを移動させたい (リネームと書いてますが、正しくは移動です)
- SDKのS3Cleintクラスには
moveObject
らしきメソッドはなく、copyObject
とdeleteObject
がある - コピー元からコピー先へコピーを実行した後に、コピー元を削除すれば、移動と同じ結果になるはず
- しかし結果は、コピーは上手くいくが、削除がうまくいかない
- コピーだけがうまくいってるので、結果的に同じオブジェクトが2つになる
という感じの現象になってしまっていたと
で、PHPはどのように書いていたかを要点だけ抜き出して書くと
<?php
use Aws\S3\S3Client;
$s3client = new S3Client([/*..色々設定..*/]);
$bucket = `hogebucket`;
$copySrc = $bucket .'/path/from/source.png';
$copyDst = 'path/to/destination.png';
$copyRes = $s3Client->copyObject([
'Bucket' => $bucket,
'CopySource' => $copySrc,
'Key' => $copyDst,
]);
$deleteRes = $s3Client->deleteObject([
'Bucket' => $bucket,
'Key' => $copySrc,
]);
お察しのいい方は、もうおわかりだと思います。凡ミスです。
削除時に Key
に与える値は、コピー時に CopySource
に与えてる同じ $copySrc
を渡しています。
これ自体は「コピーを実行した後に、コピー元を削除」という流れとしては合っているのですが、
$copySrc
は「頭にバケットがついている文字列」であったことが、ミスの始まりです。
公式リファレンスによると
- https://docs.aws.amazon.com/ja_jp/aws-sdk-php/v3/api/api-s3-2006-03-01.html#copyobject
-
https://docs.aws.amazon.com/ja_jp/aws-sdk-php/v3/api/api-s3-2006-03-01.html#deleteobject
$result = $client->copyObject([
'Bucket' => 'destinationbucket',
'CopySource' => '/sourcebucket/HappyFacejpg',
'Key' => 'HappyFaceCopyjpg',
]);
$result = $client->deleteObject([
'Bucket' => 'examplebucket',
'Key' => 'objectkey.jpg',
]);
このようにサンプルつきで書いてくれてました。
CopySource
にはバケットを含めたパスを、Key
にはバケットを含めたパスを与えなくてはいけなかったのでした。
CopySource
Required: Yes
Type: string
The name of the source bucket and key name of the source object, separated by a slash (/). Must be URL-encoded.
なので、元々のソースコードを直すとすれば
<?php
use Aws\S3\S3Client;
$s3client = new S3Client([/*..色々設定..*/]);
$bucket = `hogebucket`;
$copySrc = 'path/from/source.png';
$copyDst = 'path/to/destination.png';
$copyRes = $s3Client->copyObject([
'Bucket' => $bucket,
'CopySource' => $bucket .'/'. $copySrc,
'Key' => $copyDst,
]);
$deleteRes = $s3Client->deleteObject([
'Bucket' => $bucket,
'Key' => $copySrc,
]);
こうやってやればいいということですね。
最後に
リファレンスは、ちゃんと読みましょう・・・ (反省)
いつか、くしくも同じつまずきをしてしまった方の参考になれば幸いです
ではー